int split_on(const char *line, char delim, strlist_t *sl) { custr_t *cu = NULL; int error = 0; const char *c = line; if (custr_alloc(&cu) != 0) { error = errno; goto out; } for (;;) { char cc = *c++; if (cc == '\0') { if (custr_len(cu) > 0 && strlist_set_tail(sl, custr_cstr(cu)) != 0) { error = errno; } goto out; } else if (cc == delim) { if (strlist_set_tail(sl, custr_cstr(cu)) != 0) { error = errno; goto out; } custr_reset(cu); } else { if (custr_appendc(cu, cc) != 0) { error = errno; goto out; } } } out: custr_free(cu); errno = error; return (error == 0 ? 0 : -1); }
static void mkprog(struct sym_test *st) { char *s = NULL; custr_reset(st_custr); for (int i = 0; i < MAXHDR && st->st_hdrs[i] != NULL; i++) { addprogfmt("#include <%s>\n", st->st_hdrs[i]); } if (st->st_rtype != NULL) { for (s = st->st_rtype; *s; s++) { addprogch(*s); if (*s == '(') { s++; addprogch(*s); s++; break; } } addprogch(' '); } /* for function pointers, s is closing suffix, otherwise empty */ switch (st->st_type) { case SYM_TYPE: addprogstr("test_type;"); break; case SYM_VALUE: addprogfmt("test_value%s;\n", s); /* s usually empty */ addprogstr("void\ntest_func(void)\n{\n"); addprogfmt("\ttest_value = %s;\n}", st->st_name); break; case SYM_DEFINE: addprogfmt("#if !defined(%s)", st->st_name); if (st->st_defval != NULL) addprogfmt("|| %s != %s", st->st_name, st->st_defval); addprogfmt("\n#error %s is not defined or has the wrong value", st->st_name); addprogfmt("\n#endif\n"); break; case SYM_FUNC: addprogstr("\ntest_func("); for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) { int didname = 0; if (i > 0) { addprogstr(", "); } if (strcmp(st->st_atypes[i], "void") == 0) { didname = 1; } if (strcmp(st->st_atypes[i], "") == 0) { didname = 1; addprogstr("void"); } /* print the argument list */ for (char *a = st->st_atypes[i]; *a; a++) { if (*a == '(' && a[1] == '*' && !didname) { addprogfmt("(*a%d", i); didname = 1; a++; } else if (*a == '[' && !didname) { addprogfmt("a%d[", i); didname = 1; } else { addprogch(*a); } } if (!didname) { addprogfmt(" a%d", i); } } if (st->st_atypes[0] == NULL) { addprogstr("void"); } /* * Close argument list, and closing ")" for func ptrs. * Note that for non-function pointers, s will be empty * below, otherwise it points to the trailing argument * list. */ addprogfmt(")%s\n{\n\t", s); if (strcmp(st->st_rtype, "") != 0 && strcmp(st->st_rtype, "void") != 0) { addprogstr("return "); } /* add the function call */ addprogfmt("%s(", st->st_name); for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) { if (strcmp(st->st_atypes[i], "") != 0 && strcmp(st->st_atypes[i], "void") != 0) { addprogfmt("%sa%d", i > 0 ? ", " : "", i); } } addprogstr(");\n}"); break; } addprogch('\n'); st->st_prog = custr_cstr(st_custr); }
int parse_line(const char *line, strlist_t *sl) { custr_t *cu = NULL; state_t state = ST_WHITESPACE; const char *c = line; int error = 0; if (custr_alloc(&cu) != 0) { error = errno; goto out; } for (;;) { char cc = *c; lextype_t lextype; /* * Determine which class of character this is: */ switch (cc) { case '\0': case '#': case '\n': case '\r': lextype = LEX_ENDL; break; case ' ': case '\t': lextype = LEX_WHITESPACE; break; default: lextype = LEX_OTHER; break; } /* * Determine what to do with this character based on the class * and our current state: */ switch (state) { case ST_WHITESPACE: { switch (lextype) { case LEX_ENDL: goto out; case LEX_WHITESPACE: c++; break; case LEX_OTHER: state = ST_TOKEN; break; default: (void) printf("ST_WHITESPACE: unknown " "lextype: %d\n", lextype); abort(); } break; } case ST_TOKEN: { switch (lextype) { case LEX_ENDL: if (strlist_set_tail(sl, custr_cstr(cu)) != 0) { error = errno; goto out; } goto out; case LEX_WHITESPACE: if (strlist_set_tail(sl, custr_cstr(cu)) != 0) { error = errno; goto out; } custr_reset(cu); state = ST_WHITESPACE; break; case LEX_OTHER: if (custr_appendc(cu, cc) != 0) { error = errno; goto out; } c++; break; default: (void) printf("ST_TOKEN: unknown lextype: %d\n", lextype); abort(); } break; } default: (void) printf("unknown state: %d\n", state); abort(); } } out: custr_free(cu); errno = error; return (error == 0 ? 0 : -1); }