/* This software is public domain. No copyright is claimed. * Jon Mayo April 2012 */ #include #include #include /* Load an .ini format file * filename - path to a file * report - callback can return non-zero to stop, the callback error code is * returned from this function. * return - return 0 on success */ int ini_load(const char *filename, int (*report)(const char *section, const char *name, const char *value)) { char buf[4096]; FILE *f; int line; char *section = NULL; char *tmp; int ret = 0; f = fopen(filename, "r"); if (!f) { perror(filename); return -1; } section = strdup(""); ret = 0; line = 0; while (fgets(buf, sizeof(buf), f)) { char *base; line++; /* strip comments - TODO: check for quotes */ tmp = strchr(buf, ';'); if (tmp) *tmp = 0; base = buf + strspn(buf, " \t\r\n"); if (!*base) { continue; } else if (*base == '[') { /* is it a section? */ char *end; end = strchr(base + 1, ']'); if (!end) { /* parse error */ ret = -1; goto out; } *end = 0; free(section); section = strdup(base + 1); continue; } else if ((tmp = strchr(base, '='))) { /* name = value? */ char *name; char *value; /* find name and value */ name = base; *tmp = 0; tmp++; value = tmp; /* clean up white space */ name += strspn(name, " \t\r\n"); value += strspn(value, " \t\r\n"); tmp = strrchr(value, '\n'); if (tmp) *tmp = 0; ret = report(section, name, value); if (ret) goto out; } else { /* neither a section nor a name=value */ ret = -1; goto out; } } out: fclose(f); free(section); if (ret) fprintf(stderr, "ERROR on line %d!\n", line); return ret; } /* test code */ #if 1 static int my_callback(const char *section, const char *name, const char *value) { fprintf(stdout, "[%s] '%s'='%s'\n", section, name, value); return 0; } int main(int argc, char **argv) { int i, e; for(i = 1; i < argc; i++) { e = ini_load(argv[i], my_callback); if (e) return 1; } return 0; } #endif