+ /* Parse the configuration string. */
+ if (config) {
+
+ /* The first thing to do is find the end of the string. */
+ l = config + strlen(config);
+
+ for (;;) {
+ /* Process the whitespace-sparated words of the string one by one. */
+
+ /* Skip over any initial whitespace. If we hit the end of the string
+ * then we're done.
+ */
+ for (;;)
+ if (config >= l) goto done_config;
+ else if (!ISSPACE(*config)) break;
+ else config++;
+
+ /* There's definitely a word here. Find the end of it. */
+ for (p = config; p < l && !ISSPACE(*p); p++);
+ nn = p - config;
+
+ /* Try various simple keywords. */
+#define MATCHP(lit) (nn == sizeof(lit) - 1 && MEMCMP(config, ==, lit, nn))
+
+ if (MATCHP("list")) {
+ /* The `list' keyword requests lists of the available timer
+ * implementations.
+ */
+
+ for (i = 0; i < NTIMER; i++) {
+ printf("%s timers:", timertab[i].what);
+ for (tt = timertab[i].opstab; *tt; tt++)
+ if (!((*tt)->f)&TF_SECRET) printf(" %s", (*tt)->name);
+ putchar('\n');
+ }
+ goto next_config;
+ }
+
+#undef MATCHP
+
+ /* Otherwise it's an assignment, setting a subtimer list. */
+ p = memchr(config, '=', nn);
+ if (!p)
+ n = nn;
+ else {
+ n = p - config;
+ for (i = 0; i < NTIMER; i++)
+ if (STRNCMP(config, ==, timertab[i].what, n) &&
+ !timertab[i].what[n]) {
+ if (tmconf[i].p)
+ debug("duplicate %s timer list", timertab[i].what);
+ tmconf[i].p = config + n + 1; tmconf[i].sz = nn - n - 1;
+ goto next_config;
+ }
+ }
+ debug("unrecognized config keyword `%.*s'", (int)n, config);
+
+ /* Move on to the next word. */
+ next_config:
+ config += nn;
+ }
+ done_config:;
+ }
+
+ /* Override these settings from the environment. */
+ for (i = 0; i < NTIMER; i++) {
+ p = getenv(timertab[i].env);
+ if (p) { tmconf[i].p = p; tmconf[i].sz = strlen(p); }
+ }
+
+ /* All seems well. Allocate the timer object. */
+ t = xmalloc(sizeof(*t));
+ for (i = 0; i < NTIMER; i++) t->ops[i] = 0;
+
+ /* Try to set up the subtimers. */
+ for (i = 0; i < NTIMER; i++)
+ if (select_timer(t, i, tmconf[i].p, tmconf[i].sz)) goto end;
+
+ /* All is done. */