void printf_formattert::process_char(std::ostream &out) { char ch=next(); if(ch=='%') process_format(out); else out << ch; }
USHORT FAR prntf (NPSZ buf, NPSZ fmt, PUCHAR arg_ptr) { NPCH sptr; LONG lval; ULONG uval; fs.buf = buf; fs.off = 0; fs.fmtptr = fmt; while (process_format (&fs) != TYPE_END) { switch (fs.type) { case TYPE_STRING: sptr = va_arg (arg_ptr, NPCH); put_field (&fs, sptr); break; case TYPE_CHAR: *(short far *)(fs.buf+fs.off) = va_arg (arg_ptr, USHORT); fs.off++; break; case TYPE_PCT: *(short far *)(fs.buf+fs.off) = '%'; fs.off++; break; case TYPE_DECIMAL: lval = (fs.flags & FS_LONG) ? va_arg (arg_ptr, LONG) : va_arg (arg_ptr, INT ); cvtld (sbuf, lval); put_field (&fs, sbuf); break; case TYPE_UNSIGNED: case TYPE_HEX: uval = (fs.flags & FS_LONG) ? va_arg (arg_ptr, ULONG) : va_arg (arg_ptr, USHORT ); if (fs.type == TYPE_HEX) cvtlx (sbuf, uval); else cvtlu (sbuf, uval); put_field (&fs, sbuf); break; case TYPE_INVALID: _strncpy (fs.buf+fs.off, fs.fmtstrt, fs.fmtptr-fs.fmtstrt); fs.off += fs.fmtptr - fs.fmtstrt; break; } } return (0); }
NOINLINE void test_process_format() { int counter = 2; char character = '!'; double value = 0.5; auto print = [](auto x) { print_it(x); }; process_format(print, "val = $value$, cnt = $counter$, ch = $character$, again v=$value$;\n", counter, character, value); }
void process_table(table_input &in) { options *opt = 0; format *form = 0; table *tbl = 0; if ((opt = process_options(in)) != 0 && (form = process_format(in, opt)) != 0 && (tbl = process_data(in, form, opt)) != 0) { tbl->print(); delete tbl; } else { error("giving up on this table"); while (in.get() != EOF) ; } delete opt; delete form; if (!in.ended()) error("premature end of file"); }
table *process_data(table_input &in, format *f, options *opt) { char tab_char = opt->tab_char; int ncolumns = f->ncolumns; int current_row = 0; int format_index = 0; int give_up = 0; enum { DATA_INPUT_LINE, TROFF_INPUT_LINE, SINGLE_HLINE, DOUBLE_HLINE } type; table *tbl = new table(ncolumns, opt->flags, opt->linesize, opt->decimal_point_char); if (opt->delim[0] != '\0') tbl->set_delim(opt->delim[0], opt->delim[1]); for (;;) { // first determine what type of line this is int c = in.get(); if (c == EOF) break; if (c == '.') { int d = in.get(); if (d != EOF && csdigit(d)) { in.unget(d); type = DATA_INPUT_LINE; } else { in.unget(d); type = TROFF_INPUT_LINE; } } else if (c == '_' || c == '=') { int d = in.get(); if (d == '\n') { if (c == '_') type = SINGLE_HLINE; else type = DOUBLE_HLINE; } else { in.unget(d); type = DATA_INPUT_LINE; } } else { type = DATA_INPUT_LINE; } switch (type) { case DATA_INPUT_LINE: { string input_entry; if (format_index >= f->nrows) format_index = f->nrows - 1; // A format row that is all lines doesn't use up a data line. while (format_index < f->nrows - 1) { int cnt; for (cnt = 0; cnt < ncolumns; cnt++) { entry_format *e = f->entry[format_index] + cnt; if (e->type != FORMAT_HLINE && e->type != FORMAT_DOUBLE_HLINE // Unfortunately tbl treats a span as needing data. // && e->type != FORMAT_SPAN ) break; } if (cnt < ncolumns) break; for (cnt = 0; cnt < ncolumns; cnt++) tbl->add_entry(current_row, cnt, input_entry, f->entry[format_index] + cnt, current_filename, current_lineno); tbl->add_vlines(current_row, f->vline[format_index]); format_index++; current_row++; } entry_format *line_format = f->entry[format_index]; int col = 0; int row_comment = 0; for (;;) { if (c == tab_char || c == '\n') { int ln = current_lineno; if (c == '\n') --ln; if ((opt->flags & table::NOSPACES)) input_entry.remove_spaces(); while (col < ncolumns && line_format[col].type == FORMAT_SPAN) { tbl->add_entry(current_row, col, "", &line_format[col], current_filename, ln); col++; } if (c == '\n' && input_entry.length() == 2 && input_entry[0] == 'T' && input_entry[1] == '{') { input_entry = ""; ln++; enum { START, MIDDLE, GOT_T, GOT_RIGHT_BRACE, GOT_DOT, GOT_l, GOT_lf, END } state = START; while (state != END) { c = in.get(); if (c == EOF) break; switch (state) { case START: if (c == 'T') state = GOT_T; else if (c == '.') state = GOT_DOT; else { input_entry += c; if (c != '\n') state = MIDDLE; } break; case GOT_T: if (c == '}') state = GOT_RIGHT_BRACE; else { input_entry += 'T'; input_entry += c; state = c == '\n' ? START : MIDDLE; } break; case GOT_DOT: if (c == 'l') state = GOT_l; else { input_entry += '.'; input_entry += c; state = c == '\n' ? START : MIDDLE; } break; case GOT_l: if (c == 'f') state = GOT_lf; else { input_entry += ".l"; input_entry += c; state = c == '\n' ? START : MIDDLE; } break; case GOT_lf: if (c == ' ' || c == '\n' || compatible_flag) { string args; input_entry += ".lf"; while (c != EOF) { args += c; if (c == '\n') break; c = in.get(); } args += '\0'; interpret_lf_args(args.contents()); // remove the '\0' args.set_length(args.length() - 1); input_entry += args; state = START; } else { input_entry += ".lf"; input_entry += c; state = MIDDLE; } break; case GOT_RIGHT_BRACE: if ((opt->flags & table::NOSPACES)) { while (c == ' ') c = in.get(); if (c == EOF) break; } if (c == '\n' || c == tab_char) state = END; else { input_entry += 'T'; input_entry += '}'; input_entry += c; state = MIDDLE; } break; case MIDDLE: if (c == '\n') state = START; input_entry += c; break; case END: default: assert(0); } } if (c == EOF) { error("end of data in middle of text block"); give_up = 1; break; } } if (col >= ncolumns) { if (!input_entry.empty()) { if (input_entry.length() >= 2 && input_entry[0] == '\\' && input_entry[1] == '"') row_comment = 1; else if (!row_comment) { if (c == '\n') in.unget(c); input_entry += '\0'; error("excess data entry `%1' discarded", input_entry.contents()); if (c == '\n') (void)in.get(); } } } else tbl->add_entry(current_row, col, input_entry, &line_format[col], current_filename, ln); col++; if (c == '\n') break; input_entry = ""; } else input_entry += c; c = in.get(); if (c == EOF) break; } if (give_up) break; input_entry = ""; for (; col < ncolumns; col++) tbl->add_entry(current_row, col, input_entry, &line_format[col], current_filename, current_lineno - 1); tbl->add_vlines(current_row, f->vline[format_index]); current_row++; format_index++; } break; case TROFF_INPUT_LINE: { string line; int ln = current_lineno; for (;;) { line += c; if (c == '\n') break; c = in.get(); if (c == EOF) { break; } } tbl->add_text_line(current_row, line, current_filename, ln); if (line.length() >= 4 && line[0] == '.' && line[1] == 'T' && line[2] == '&') { format *newf = process_format(in, opt, f); if (newf == 0) give_up = 1; else f = newf; } if (line.length() >= 3 && line[0] == '.' && line[1] == 'l' && line[2] == 'f') { line += '\0'; interpret_lf_args(line.contents() + 3); } } break; case SINGLE_HLINE: tbl->add_single_hline(current_row); break; case DOUBLE_HLINE: tbl->add_double_hline(current_row); break; default: assert(0); } if (give_up) break; } if (!give_up && current_row == 0) { error("no real data"); give_up = 1; } if (give_up) { delete tbl; return 0; } // Do this here rather than at the beginning in case continued formats // change it. int i; for (i = 0; i < ncolumns - 1; i++) if (f->separation[i] >= 0) tbl->set_column_separation(i, f->separation[i]); for (i = 0; i < ncolumns; i++) if (!f->width[i].empty()) tbl->set_minimum_width(i, f->width[i]); for (i = 0; i < ncolumns; i++) if (f->equal[i]) tbl->set_equal_column(i); return tbl; }