static inline int lengthOfEscapeSequence(const QByteArray &s, int i) { if (s.at(i) != '\\' || i >= s.length() - 1) return 1; const int startPos = i; ++i; char ch = s.at(i); if (ch == 'x') { ++i; while (i < s.length() && is_hex_char(s.at(i))) ++i; } else if (is_octal_char(ch)) { while (i < startPos + 4 && i < s.length() && is_octal_char(s.at(i))) { ++i; } } else { // single character escape sequence i = qMin(i + 1, s.length()); } return i - startPos; }
static char parse_octal_escape(const char *p, size_t *consumed) { register int n, i; size_t pos = 0; for (i = n = 0; i < 3 && is_octal_char(p[pos]); i++, pos++) { n = 8 * n + p[pos] - '0'; } --pos; *consumed = pos; return n; }
bool insert_fprintf (struct format_val *vec, const struct parser_table *entry, char *format) { char *segstart = format; char *fmt_editpos; /* Current address in scanning `format'. */ struct segment **segmentp; /* Address of current segment. */ struct predicate *our_pred; our_pred = insert_primary_withpred (entry, pred_fprintf, format); our_pred->side_effects = our_pred->no_default_print = true; our_pred->args.printf_vec = *vec; our_pred->need_type = false; our_pred->need_stat = false; our_pred->p_cost = NeedsNothing; segmentp = &our_pred->args.printf_vec.segment; *segmentp = NULL; for (fmt_editpos = segstart; *fmt_editpos; fmt_editpos++) { if (fmt_editpos[0] == '\\' && fmt_editpos[1] == 'c') { make_segment (segmentp, segstart, fmt_editpos - segstart, KIND_STOP, 0, 0, our_pred); if (our_pred->need_stat && (our_pred->p_cost < NeedsStatInfo)) our_pred->p_cost = NeedsStatInfo; return true; } else if (*fmt_editpos == '\\') { size_t readpos = 1; if (!fmt_editpos[readpos]) { error (0, 0, _("warning: escape `\\' followed by nothing at all")); --readpos; /* (*fmt_editpos) is already '\\' and that's a reasonable result. */ } else if (is_octal_char(fmt_editpos[readpos])) { size_t consumed = 0; *fmt_editpos = parse_octal_escape(fmt_editpos + readpos, &consumed); readpos += consumed; } else { const char val = parse_escape_char(fmt_editpos[readpos]); if (val) { fmt_editpos[0] = val; } else { error (0, 0, _("warning: unrecognized escape `\\%c'"), fmt_editpos[readpos]); fmt_editpos += readpos; continue; } } segmentp = make_segment (segmentp, segstart, fmt_editpos - segstart + 1, KIND_PLAIN, 0, 0, our_pred); segstart = fmt_editpos + readpos + 1; /* Move past the escape. */ fmt_editpos += readpos; /* Incremented immediately by `for'. */ } else if (fmt_editpos[0] == '%') { size_t len; if (fmt_editpos[1] == 0) { /* Trailing %. We don't like those. */ error (EXIT_FAILURE, 0, _("error: %s at end of format string"), fmt_editpos); } if (fmt_editpos[1] == '%') /* %% produces just %. */ len = 1; else len = get_format_flags_length(fmt_editpos); fmt_editpos += len; len = get_format_specifer_length (fmt_editpos[0]); if (len && (fmt_editpos[len-1])) { const char fmt2 = (len == 2) ? fmt_editpos[1] : 0; segmentp = make_segment (segmentp, segstart, fmt_editpos - segstart, KIND_FORMAT, fmt_editpos[0], fmt2, our_pred); fmt_editpos += (len - 1); } else { if (strchr ("{[(", fmt_editpos[0])) { error (EXIT_FAILURE, 0, _("error: the format directive `%%%c' is reserved for future use"), (int)fmt_editpos[0]); /*NOTREACHED*/ } if (len == 2 && !fmt_editpos[1]) { error (0, 0, _("warning: format directive `%%%c' " "should be followed by another character"), fmt_editpos[0]); } else { /* An unrecognized % escape. Print the char after the %. */ error (0, 0, _("warning: unrecognized format directive `%%%c'"), fmt_editpos[0]); } segmentp = make_segment (segmentp, segstart, fmt_editpos + 1 - segstart, KIND_PLAIN, 0, 0, our_pred); } segstart = fmt_editpos + 1; } } if (fmt_editpos > segstart) make_segment (segmentp, segstart, fmt_editpos - segstart, KIND_PLAIN, 0, 0, our_pred); return true; }