static int addunit(struct unittype * theunit, const char *toadd, int flip) { char *scratch, *savescr; char *item; char *divider, *slash; int doingtop; savescr = scratch = dupstr(toadd); for (slash = scratch + 1; *slash; slash++) if (*slash == '-' && (tolower((unsigned char)*(slash - 1)) != 'e' || !strchr(".0123456789", *(slash + 1)))) *slash = ' '; slash = strchr(scratch, '/'); if (slash) *slash = 0; doingtop = 1; do { item = strtok(scratch, " *\t\n/"); while (item) { if (strchr("0123456789.", *item)) { /* item starts with a number */ char *endptr; double num; divider = strchr(item, '|'); if (divider) { *divider = 0; num = strtod(item, &endptr); if (!num) { zeroerror(); return 1; } if (endptr != divider) { /* "6foo|2" is an error */ mywarnx("Junk before '|'"); return 1; } if (doingtop ^ flip) theunit->factor *= num; else theunit->factor /= num; num = strtod(divider + 1, &endptr); if (!num) { zeroerror(); return 1; } if (doingtop ^ flip) theunit->factor /= num; else theunit->factor *= num; if (*endptr) { /* "6|2foo" is like "6|2 foo" */ item = endptr; continue; } } else { num = strtod(item, &endptr); if (!num) { zeroerror(); return 1; } if (doingtop ^ flip) theunit->factor *= num; else theunit->factor /= num; if (*endptr) { /* "3foo" is like "3 foo" */ item = endptr; continue; } } } else { /* item is not a number */ int repeat = 1; if (strchr("23456789", item[strlen(item) - 1])) { repeat = item[strlen(item) - 1] - '0'; item[strlen(item) - 1] = 0; } for (; repeat; repeat--) if (addsubunit(doingtop ^ flip ? theunit->numerator : theunit->denominator, item)) return 1; } item = strtok(NULL, " *\t/\n"); } doingtop--; if (slash) { scratch = slash + 1; } else doingtop--; } while (doingtop >= 0); free(savescr); return 0; }
int addunit(struct unittype * theunit, char *toadd, int flip, int quantity) { char *scratch, *savescr; char *item; char *divider, *slash, *offset; int doingtop; if (!strlen(toadd)) return 1; savescr = scratch = dupstr(toadd); for (slash = scratch + 1; *slash; slash++) if (*slash == '-' && (tolower(*(slash - 1)) != 'e' || !strchr(".0123456789", *(slash + 1)))) *slash = ' '; slash = strchr(scratch, '/'); if (slash) *slash = 0; doingtop = 1; do { item = strtok(scratch, " *\t\n/"); while (item) { if (strchr("0123456789.", *item)) { /* item is a number */ double num, offsetnum; if (quantity) theunit->quantity = 1; offset = strchr(item, '&'); if (offset) { *offset = 0; offsetnum = atof(offset+1); } else offsetnum = 0.0; divider = strchr(item, '|'); if (divider) { *divider = 0; num = atof(item); if (!num) { zeroerror(); return 1; } if (doingtop ^ flip) { theunit->factor *= num; theunit->offset *= num; } else { theunit->factor /= num; theunit->offset /= num; } num = atof(divider + 1); if (!num) { zeroerror(); return 1; } if (doingtop ^ flip) { theunit->factor /= num; theunit->offset /= num; } else { theunit->factor *= num; theunit->offset *= num; } } else { num = atof(item); if (!num) { zeroerror(); return 1; } if (doingtop ^ flip) { theunit->factor *= num; theunit->offset *= num; } else { theunit->factor /= num; theunit->offset /= num; } } if (doingtop ^ flip) theunit->offset += offsetnum; } else { /* item is not a number */ int repeat = 1; if (strchr("23456789", item[strlen(item) - 1])) { repeat = item[strlen(item) - 1] - '0'; item[strlen(item) - 1] = 0; } for (; repeat; repeat--) if (addsubunit(doingtop ^ flip ? theunit->numerator : theunit->denominator, item)) return 1; } item = strtok(NULL, " *\t/\n"); } doingtop--; if (slash) { scratch = slash + 1; } else doingtop--; } while (doingtop >= 0); free(savescr); return 0; }