#include #include #ifdef HAVE_STDLIB_H #include #endif #include #include #include "prof_int.h" #define SECTION_SEP_CHAR '/' #define STATE_INIT_COMMENT 1 #define STATE_STD_LINE 2 #define STATE_GET_OBRACE 3 struct parse_state { int state; int group_level; struct profile_node *root_section; struct profile_node *current_section; }; static char *skip_over_blanks(cp) char *cp; { while (*cp && isspace(*cp)) cp++; return cp; } static void strip_line(line) char *line; { char *p; while (*line) { p = line + strlen(line) - 1; if ((*p == '\n') || (*p == '\r')) *p = 0; else break; } } static errcode_t parse_init_state(state) struct parse_state *state; { state->state = STATE_INIT_COMMENT; state->group_level = 0; return profile_create_node("(root)", 0, &state->root_section); } static errcode_t parse_std_line(line, state) char *line; struct parse_state *state; { char *cp, ch, *tag, *value; char *p; errcode_t retval; int do_subsection = 0; void *iter = 0; if (*line == 0) return 0; if (line[0] == ';') return 0; strip_line(line); cp = skip_over_blanks(line); ch = *cp; if (ch == 0) return 0; if (ch == '[') { if (state->group_level > 0) return PROF_SECTION_NOTOP; cp++; p = strchr(cp, ']'); if (p == NULL) return PROF_SECTION_SYNTAX; *p = '\0'; retval = profile_find_node_subsection(state->root_section, cp, &iter, 0, &state->current_section); if (retval == PROF_NO_SECTION) { retval = profile_add_node(state->root_section, cp, 0, &state->current_section); if (retval) return retval; } else if (retval) return retval; /* * Finish off the rest of the line. */ cp = p+1; if (*cp) return PROF_SECTION_SYNTAX; return 0; } if (ch == '}') { if (state->group_level == 0) return PROF_EXTRA_CBRACE; retval = profile_get_node_parent(state->current_section, &state->current_section); if (retval) return retval; state->group_level--; return 0; } /* * Parse the relations */ tag = cp; cp = strchr(cp, '='); if (!cp) return PROF_RELATION_SYNTAX; *cp = '\0'; p = strchr(tag, ' '); if (p) { *p = '\0'; p = skip_over_blanks(p+1); if (p != cp) return PROF_RELATION_SYNTAX; } cp = skip_over_blanks(cp+1); value = cp; if (value[0] == 0) { do_subsection++; state->state = STATE_GET_OBRACE; } if (value[0] == '{' && value[1] == 0) do_subsection++; if (do_subsection) { retval = profile_add_node(state->current_section, tag, 0, &state->current_section); if (retval) return retval; state->group_level++; return 0; } profile_add_node(state->current_section, tag, value, 0); return 0; } static errcode_t parse_line(line, state) char *line; struct parse_state *state; { char *cp; switch (state->state) { case STATE_INIT_COMMENT: if (line[0] != '[') return 0; state->state = STATE_STD_LINE; case STATE_STD_LINE: return parse_std_line(line, state); case STATE_GET_OBRACE: cp = skip_over_blanks(line); if (*cp != '{') return PROF_MISSING_OBRACE; state->state = STATE_STD_LINE; } return 0; } errcode_t profile_parse_file(f, root) FILE *f; struct profile_node **root; { #define BUF_SIZE 2048 char *bptr; errcode_t retval; struct parse_state state; bptr = malloc (BUF_SIZE); if (!bptr) return ENOMEM; retval = parse_init_state(&state); if (retval) { free (bptr); return retval; } while (!feof(f)) { if (fgets(bptr, BUF_SIZE, f) == NULL) break; retval = parse_line(bptr, &state); if (retval) { free (bptr); return retval; } } *root = state.root_section; free (bptr); return 0; } #if defined(_MSDOS) || defined(_WIN32) #define EOL "\r\n" #endif #ifdef _MACINTOSH #define EOL "\r" #endif #ifndef EOL #define EOL "\n" #endif #if !defined(_MSDOS) && !defined(_WIN32) void dump_profile(root, level) struct profile_node *root; int level; { int i; struct profile_node *p; void *iter; long retval; char *name, *value; iter = 0; do { retval = profile_find_node_relation(root, 0, &iter, &name, &value); if (retval) break; for (i=0; i < level; i++) printf(" "); printf("%s = '%s'%s", name, value, EOL); } while (iter != 0); iter = 0; do { retval = profile_find_node_subsection(root, 0, &iter, &name, &p); if (retval) break; for (i=0; i < level; i++) printf(" "); printf("[%s]%s", name, EOL); dump_profile(p, level+1); } while (iter != 0); } #endif /* !_MSDOS && !_WIN32 */ void dump_profile_to_file(root, level, dstfile) struct profile_node *root; int level; FILE *dstfile; { int i; struct profile_node *p; void *iter; long retval; char *name, *value; iter = 0; do { retval = profile_find_node_relation(root, 0, &iter, &name, &value); if (retval) break; for (i=0; i < level; i++) fprintf(dstfile, "\t"); fprintf(dstfile, "%s = %s%s", name, value, EOL); } while (iter != 0); iter = 0; do { retval = profile_find_node_subsection(root, 0, &iter, &name, &p); if (retval) break; if (level == 0) { /* [xxx] */ for (i=0; i < level; i++) fprintf(dstfile, "\t"); fprintf(dstfile, "[%s]%s", name, EOL); dump_profile_to_file(p, level+1, dstfile); fprintf(dstfile, EOL); } else { /* xxx = { ... } */ for (i=0; i < level; i++) fprintf(dstfile, "\t"); fprintf(dstfile, "%s = {%s", name, EOL); dump_profile_to_file(p, level+1, dstfile); for (i=0; i < level; i++) fprintf(dstfile, "\t"); fprintf(dstfile, "}%s", EOL); } } while (iter != 0); }