diff options
Diffstat (limited to 'src/util/profile')
-rw-r--r-- | src/util/profile/ChangeLog | 18 | ||||
-rw-r--r-- | src/util/profile/prof_parse.c | 113 | ||||
-rw-r--r-- | src/util/profile/prof_tree.c | 20 |
3 files changed, 136 insertions, 15 deletions
diff --git a/src/util/profile/ChangeLog b/src/util/profile/ChangeLog index 9bfcde8..3e61d02 100644 --- a/src/util/profile/ChangeLog +++ b/src/util/profile/ChangeLog @@ -1,3 +1,21 @@ +1998-08-06 Theodore Ts'o <tytso@rsts-11.mit.edu> + + * prof_tree.c (profile_delete_node_relation): Fix bug where + deleting a node would corrupt the linked list. + (profile_add_node): Fix another linked list corruption + problem where an insertion into the middle of the linked + list didn't update a previous link. [krb5-libs/615] + +Fri Jan 23 20:55:06 1998 Theodore Ts'o <tytso@rsts-11.mit.edu> + + * prof_parse.c (parse_std_line, parse_quoted_string, + need_double_quotes, output_quoted_string, dump_profile, + dump_profile_to_file): Vastly improved the profile + parsing; whitespace at the end of lines are now ignored. + Added quoted string parsing, complete with backquote + processing. Strings which need to be quoted are properly + quoted on output. + Mon Nov 4 17:04:51 1996 Theodore Y. Ts'o <tytso@mit.edu> * prof_parse.c (parse_std_line): Accept either ';' or '#' on the diff --git a/src/util/profile/prof_parse.c b/src/util/profile/prof_parse.c index 941cc33..e7e72b8 100644 --- a/src/util/profile/prof_parse.c +++ b/src/util/profile/prof_parse.c @@ -43,6 +43,36 @@ static void strip_line(line) } } +static void parse_quoted_string(char *str) +{ + char *to, *from; + + to = from = str; + + for (to = from = str; *from && *from != '"'; to++, from++) { + if (*from == '\\') { + from++; + switch (*from) { + case 'n': + *to = '\n'; + break; + case 't': + *to = '\t'; + break; + case 'b': + *to = '\b'; + break; + default: + *to = *from; + } + continue; + } + *to = *from; + } + *to = '\0'; +} + + static errcode_t parse_init_state(state) struct parse_state *state; { @@ -126,12 +156,19 @@ static errcode_t parse_std_line(line, state) } cp = skip_over_blanks(cp+1); value = cp; - if (value[0] == 0) { + if (value[0] == '"') { + value++; + parse_quoted_string(value); + } else if (value[0] == 0) { do_subsection++; state->state = STATE_GET_OBRACE; - } - if (value[0] == '{' && value[1] == 0) + } else if (value[0] == '{' && value[1] == 0) do_subsection++; + else { + cp = value + strlen(value) - 1; + while ((cp > value) && isspace(*cp)) + *cp-- = 0; + } if (do_subsection) { retval = profile_add_node(state->current_section, tag, 0, &state->current_section); @@ -200,6 +237,60 @@ errcode_t profile_parse_file(f, root) return 0; } +/* + * Return TRUE if the string begins or ends with whitespace + */ +static int need_double_quotes(str) + char *str; +{ + if (!str || !*str) + return 0; + if (isspace(*str) ||isspace(*(str + strlen(str) - 1))) + return 1; + if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b')) + return 1; + return 0; +} + +/* + * Output a string with double quotes, doing appropriate backquoting + * of characters as necessary. + */ +static void output_quoted_string(str, f) + char *str; + FILE *f; +{ + char ch; + + fputc('"', f); + if (!str) { + fputc('"', f); + return; + } + while (ch = *str++) { + switch (ch) { + case '\\': + fputs("\\\\", f); + break; + case '\n': + fputs("\\n", f); + break; + case '\t': + fputs("\\t", f); + break; + case '\b': + fputs("\\b", f); + break; + default: + fputc(ch, f); + break; + } + } + fputc('"', f); +} + + + #if defined(_MSDOS) || defined(_WIN32) #define EOL "\r\n" #endif @@ -232,7 +323,13 @@ void dump_profile(root, level) break; for (i=0; i < level; i++) printf(" "); - printf("%s = '%s'%s", name, value, EOL); + if (need_double_quotes(value)) { + fputs(name, stdout); + fputs(" = ", stdout); + output_quoted_string(value, stdout); + fputs(EOL, stdout); + } else + printf("%s = '%s'%s", name, value, EOL); } while (iter != 0); iter = 0; @@ -269,7 +366,13 @@ void dump_profile_to_file(root, level, dstfile) break; for (i=0; i < level; i++) fprintf(dstfile, "\t"); - fprintf(dstfile, "%s = %s%s", name, value, EOL); + if (need_double_quotes(value)) { + fputs(name, dstfile); + fputs(" = ", dstfile); + output_quoted_string(value, dstfile); + fputs(EOL, dstfile); + } else + fprintf(dstfile, "%s = %s%s", name, value, EOL); } while (iter != 0); iter = 0; diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c index a192e1d..24b447e 100644 --- a/src/util/profile/prof_tree.c +++ b/src/util/profile/prof_tree.c @@ -145,9 +145,14 @@ errcode_t profile_add_node(section, name, value, ret_node) if (section->value) return PROF_ADD_NOT_SECTION; + /* + * Find the place to insert the new node. We look for the + * place *after* the last match of the node name, since + * order matters. + */ for (p=section->first_child, last = 0; p; last = p, p = p->next) { cmp = strcmp(p->name, name); - if (cmp >= 0) + if (cmp > 0) break; } retval = profile_create_node(name, value, &new); @@ -155,19 +160,14 @@ errcode_t profile_add_node(section, name, value, ret_node) return retval; new->group_level = section->group_level+1; new->parent = section; - if (cmp == 0) { - do { - last = p; - p = p->next; - } while (p && strcmp(p->name, name) == 0); - } new->prev = last; + new->next = p; + if (p) + p->prev = new; if (last) last->next = new; else section->first_child = new; - if (p) - new->next = p; if (ret_node) *ret_node = new; return 0; @@ -317,7 +317,7 @@ errcode_t profile_delete_node_relation(section, name) section->first_child = p->next; next = p->next; if (p->next) - p->next->prev = p; + p->next->prev = p->prev; profile_free_node(p); p = next; } |