📄 main.cc
字号:
list->vline = 2; error("more than 2 vertical bars between key letters"); } if (c == '\n' || c == ',') { c = in.get(); list->last_column = 1; } } if (c == '.') { do { c = in.get(); } while (c == ' ' || c == '\t'); if (c != '\n') { error("`.' not last character on line"); free_input_entry_format_list(list); return 0; } } if (!list) { error("no format"); free_input_entry_format_list(list); return 0; } list->last_column = 1; // now reverse the list so that the first row is at the beginning input_entry_format *rev = 0; while (list != 0) { input_entry_format *tem = list->next; list->next = rev; rev = list; list = tem; } list = rev; input_entry_format *tem;#if 0 for (tem = list; tem; tem = tem->next) tem->debug_print(); putc('\n', stderr);#endif // compute number of columns and rows int ncolumns = 0; int nrows = 0; int col = 0; for (tem = list; tem; tem = tem->next) { if (tem->last_column) { if (col >= ncolumns) ncolumns = col + 1; col = 0; nrows++; } else col++; } int row; format *f; if (current_format) { if (ncolumns > current_format->ncolumns) { error("cannot increase the number of columns in a continued format"); free_input_entry_format_list(list); return 0; } f = current_format; row = f->nrows; f->add_rows(nrows); } else { f = new format(nrows, ncolumns); row = 0; } col = 0; for (tem = list; tem; tem = tem->next) { f->entry[row][col] = *tem; if (col < ncolumns-1) { // use the greatest separation if (tem->separation > f->separation[col]) { if (current_format) error("cannot change column separation in continued format"); else f->separation[col] = tem->separation; } } else if (tem->separation >= 0) error("column separation specified for last column"); if (tem->equal && !f->equal[col]) { if (current_format) error("cannot change which columns are equal in continued format"); else f->equal[col] = 1; } if (!tem->width.empty()) { // use the last width if (!f->width[col].empty() && f->width[col] != tem->width) error("multiple widths for column %1", col+1); f->width[col] = tem->width; } if (tem->pre_vline) { assert(col == 0); f->vline[row][col] = tem->pre_vline; } f->vline[row][col+1] = tem->vline; if (tem->last_column) { row++; col = 0; } else col++; } free_input_entry_format_list(list); for (col = 0; col < ncolumns; col++) { entry_format *e = f->entry[f->nrows-1] + col; if (e->type != FORMAT_HLINE && e->type != FORMAT_DOUBLE_HLINE && e->type != FORMAT_SPAN) break; } if (col >= ncolumns) { error("last row of format is all lines"); delete f; return 0; } return f;}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) { for (int c = 0; c < ncolumns; c++) { entry_format *e = f->entry[format_index] + c; if (e->type != FORMAT_HLINE && e->type != FORMAT_DOUBLE_HLINE // Unfortunately tbl treats a span as needing data. // && e->type != FORMAT_SPAN ) break; } if (c < ncolumns) break; for (c = 0; c < ncolumns; c++) tbl->add_entry(current_row, c, input_entry, f->entry[format_index] + c, 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; for (;;) { if (c == tab_char || c == '\n') { int ln = current_lineno; if (c == '\n') --ln; 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 (c == '\n' || c == tab_char) state = END; else { input_entry += 'T'; input_entry += '}'; input_entry += c; state = c == '\n' ? START : 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 (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] == 'f' && 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. for (int 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;}void process_table(table_input &in){ int c; 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 ((c = in.get()) != EOF) ; } delete opt; delete form; if (!in.ended()) error("premature end of file");}static void usage(){ fprintf(stderr, "usage: %s [ -vC ] [ files... ]\n", program_name); exit(1);}int main(int argc, char **argv){ program_name = argv[0]; static char stderr_buf[BUFSIZ]; setbuf(stderr, stderr_buf); int opt; while ((opt = getopt(argc, argv, "vC")) != EOF) switch (opt) { case 'C': compatible_flag = 1; break; case 'v': { extern const char *version_string; fprintf(stderr, "GNU tbl version %s\n", version_string); fflush(stderr); break; } case '?': usage(); break; default: assert(0); } printf(".if !\\n(.g .ab GNU tbl requires GNU troff.\n" ".if !dTS .ds TS\n" ".if !dTE .ds TE\n"); if (argc > optind) { for (int i = optind; i < argc; i++) if (argv[i][0] == '-' && argv[i][1] == '\0') { current_filename = "-"; current_lineno = 1; printf(".lf 1 -\n"); process_input_file(stdin); } else { errno = 0; FILE *fp = fopen(argv[i], "r"); if (fp == 0) { current_lineno = -1; error("can't open `%1': %2", argv[i], strerror(errno)); } else { current_lineno = 1; current_filename = argv[i]; printf(".lf 1 %s\n", current_filename); process_input_file(fp); } } } else { current_filename = "-"; current_lineno = 1; printf(".lf 1 -\n"); process_input_file(stdin); } if (ferror(stdout) || fflush(stdout) < 0) fatal("output error"); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -