Devsize devsize(Device *d) { for (;;) switch(d->type) { case Devcw: case Devro: return cwsize(d); case Devjuke: d = d->j.m; break; case Devwren: return wrensize(d); case Devworm: case Devlworm: return wormsize(d); case Devfworm: return fwormsize(d); case Devmcat: return mcatsize(d); case Devmlev: return mlevsize(d); case Devmirr: return mirrsize(d); case Devpart: return partsize(d); case Devswab: d = d->swab.d; break; default: panic("illegal device in devsize: %Z", d); return 0; } }
/* We want "finished in100 seconds to match "finished in 5 seconds". */ struct pattern *get_pattern(const char *line, struct values **vals) { enum pattern_type state = LITERAL; size_t len, i, max_parts = 3; struct pattern_part part; struct pattern *p; *vals = malloc(valsize(max_parts)); p = malloc(partsize(max_parts)); p->text = line; p->num_parts = 0; for (i = len = 0; state != TERM; i++, len++) { enum pattern_type old_state = state; bool starts_num; union val v; starts_num = (line[i] == '-' && cisdigit(line[i+1])) || cisdigit(line[i]); switch (state) { case LITERAL: if (starts_num) { state = INTEGER; break; } else if (cisspace(line[i])) { state = PRESPACES; break; } break; case PRESPACES: if (starts_num) { state = INTEGER; break; } else if (!cisspace(line[i])) { state = LITERAL; } break; case INTEGER: if (line[i] == '.') { if (cisdigit(line[i+1])) { /* Was float all along... */ state = old_state = FLOAT; } else state = LITERAL; break; } /* fall thru */ case FLOAT: if (cisspace(line[i])) { state = PRESPACES; break; } else if (!cisdigit(line[i])) { state = LITERAL; break; } break; case TERM: abort(); } if (!line[i]) state = TERM; if (state == old_state) continue; part.type = old_state; part.len = len; part.off = i - len; /* Make sure identical values memcmp in find_literal_numbers */ memset(&v, 0, sizeof(v)); if (old_state == FLOAT) { char *end; v.dval = strtod(line + part.off, &end); if (end != line + i) { warnx("Could not parse float '%.*s'", (int)len, line + i - len); } else { add_part(&p, vals, &part, &v, &max_parts); } len = 0; } else if (old_state == INTEGER) { char *end; v.ival = strtoll(line + part.off, &end, 10); if (end != line + i) { warnx("Could not parse integer '%.*s'", (int)len, line + i - len); } else { add_part(&p, vals, &part, &v, &max_parts); } len = 0; } else if (old_state == LITERAL && len > 0) { /* Since we can go to PRESPACES and back, we can * have successive literals. Collapse them. */ if (p->num_parts > 0 && p->part[p->num_parts-1].type == LITERAL) { p->part[p->num_parts-1].len += len; len = 0; continue; } add_part(&p, vals, &part, &v, &max_parts); len = 0; } } return p; }