* find/print.c (get_format_flags_length): Factor out of insert_fprintf; computes the length of the format flags for a format specifier (that is everything after the % but before the format control character). (get_format_specifer_length): Also factored out of insert_fprintf; returns the number of format control characters (e.g. 2 for %A@) or 0 for error. (insert_fprintf): Keep fmt_editpos and fmt_inpos more closely in step, instead of initialising fmt_inpos only when we need it (the idea eventually will be to make fmt_inpos the loop control variable). Call get_format_specifer_length and get_format_flags_length when needed. Reduce the number of different calls to make_segment. We now have one for each KIND_ value plus one for the error case. --- ChangeLog | 18 +++++++++ find/print.c | 116 ++++++++++++++++++++++++++++++++++++---------------------- 2 files changed, 90 insertions(+), 44 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 0bd6aaf..2e477d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2011-06-28 James Youngman <[email protected]> + + Refactor insert_fprintf to minimise calls to make_segment. + * find/print.c (get_format_flags_length): Factor out of + insert_fprintf; computes the length of the format flags for a + format specifier (that is everything after the % but before the + format control character). + (get_format_specifer_length): Also factored out of insert_fprintf; + returns the number of format control characters (e.g. 2 for %A@) + or 0 for error. + (insert_fprintf): Keep fmt_editpos and fmt_inpos more closely in + step, instead of initialising fmt_inpos only when we need it (the + idea eventually will be to make fmt_inpos the loop control + variable). Call get_format_specifer_length and + get_format_flags_length when needed. Reduce the number of + different calls to make_segment. We now have one for each KIND_ + value plus one for the error case. + 2011-06-27 James Youngman <[email protected]> Factor some of the code out of insert_fprintf. diff --git a/find/print.c b/find/print.c index fc72591..862be43 100644 --- a/find/print.c +++ b/find/print.c @@ -272,6 +272,41 @@ parse_escape_char(const char ch) } +static size_t +get_format_flags_length(const char *p) +{ + size_t n = 0; + /* Scan past flags, width and precision, to verify kind. */ + for (; p[++n] && strchr ("-+ #", p[n]);) + { + /* Do nothing. */ + } + while (ISDIGIT (p[n])) + n++; + if (p[n] == '.') + for (n++; ISDIGIT (p[n]); n++) + /* Do nothing. */ ; + return n; +} + +static size_t +get_format_specifer_length(char ch) +{ + if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ%", ch)) + { + return 1; + } + else if (strchr ("ABCT", ch)) + { + return 2; + } + else + { + return 0; + } +} + + bool insert_fprintf (struct format_val *vec, const struct parser_table *entry, @@ -335,72 +370,65 @@ insert_fprintf (struct format_val *vec, } else if (fmt_editpos[0] == '%') { - if (fmt_editpos[1] == '%') - { - /* % escapes itself. That is, %% produces just %. */ - fmt_inpos = fmt_editpos+1; - } - else if (fmt_editpos[1] == 0) + size_t len; + fmt_inpos = fmt_editpos; + if (fmt_inpos[1] == 0) { /* Trailing %. We don't like those. */ error (EXIT_FAILURE, 0, - _("error: %s at end of format string"), fmt_editpos); + _("error: %s at end of format string"), fmt_inpos); } + + if (fmt_inpos[1] == '%') /* %% produces just %. */ + len = 1; else + len = get_format_flags_length(fmt_inpos); + fmt_inpos += len; + fmt_editpos += len; + + assert (fmt_inpos == fmt_editpos); + len = get_format_specifer_length (fmt_inpos[0]); + if (len && (fmt_inpos[len-1])) { - /* Scan past flags, width and precision, to verify kind. */ - for (fmt_inpos = fmt_editpos; - *++fmt_inpos && strchr ("-+ #", *fmt_inpos);) - { - /* Do nothing. */ - } - while (ISDIGIT (*fmt_inpos)) - fmt_inpos++; - if (*fmt_inpos == '.') - for (fmt_inpos++; ISDIGIT (*fmt_inpos); fmt_inpos++) - /* Do nothing. */ ; - } - if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ%", *fmt_inpos)) - { - segmentp = make_segment (segmentp, segstart, fmt_inpos - segstart, - KIND_FORMAT, *fmt_inpos, 0, - our_pred); - fmt_editpos = fmt_inpos; - segstart = fmt_editpos + 1; - } - else if (strchr ("ABCT", *fmt_inpos) && fmt_inpos[1]) - { - segmentp = make_segment (segmentp, segstart, fmt_inpos - segstart, - KIND_FORMAT, fmt_inpos[0], fmt_inpos[1], + const char fmt2 = (len == 2) ? fmt_inpos[1] : 0; + segmentp = make_segment (segmentp, segstart, + fmt_editpos - segstart, + KIND_FORMAT, *fmt_inpos, fmt2, our_pred); - fmt_editpos = fmt_inpos + 1; - segstart = fmt_editpos + 1; + fmt_editpos += (len - 1); + fmt_inpos += (len - 1); } else { - switch (*fmt_inpos) + if (strchr ("{[(", *fmt_inpos)) { - case '{': - case '[': - case '(': error (EXIT_FAILURE, 0, _("error: the format directive `%%%c' is reserved for future use"), (int)*fmt_inpos); /*NOTREACHED*/ - break; + } - default: + if (len == 2 && !fmt_inpos[1]) + { + error (0, 0, + _("warning: format directive `%%%c' " + "should be followed by another character"), + *fmt_inpos); + } + else + { /* An unrecognized % escape. Print the char after the %. */ error (0, 0, _("warning: unrecognized format directive `%%%c'"), *fmt_inpos); - segmentp = make_segment (segmentp, - segstart, fmt_editpos - segstart, - KIND_PLAIN, 0, 0, - our_pred); - segstart = fmt_editpos + 1; } + ++fmt_inpos; + segmentp = make_segment (segmentp, + segstart, fmt_inpos - segstart, + KIND_PLAIN, 0, 0, + our_pred); } + segstart = fmt_editpos + 1; } } -- 1.7.2.5
