void alter_format() { symbol nm = get_name(1); if (nm.is_null()) { skip_line(); return; } reg *r = (reg *)number_reg_dictionary.lookup(nm); if (r == 0) { r = new number_reg; number_reg_dictionary.define(nm, r); } tok.skip(); char c = tok.ch(); if (csdigit(c)) { int n = 0; do { ++n; tok.next(); } while (csdigit(tok.ch())); r->alter_format('1', n); } else if (c == 'i' || c == 'I' || c == 'a' || c == 'A') r->alter_format(c); else if (tok.newline() || tok.eof()) warning(WARN_MISSING, "missing number register format"); else error("bad number register format (got %1)", tok.description()); skip_line(); }
static int store_key(char *s, int len) { if (len < shortest_len) return 0; int is_number = 1; for (int i = 0; i < len; i++) if (!csdigit(s[i])) { is_number = 0; s[i] = cmlower(s[i]); } if (is_number && !(len == 4 && s[0] == '1' && s[1] == '9')) return 0; int h = hash(s, len) % hash_table_size; if (common_words_table) { for (word_list *ptr = common_words_table[h]; ptr; ptr = ptr->next) if (len == ptr->len && memcmp(s, ptr->str, len) == 0) return 0; } table_entry *pp = hash_table + h; if (!pp->ptr) pp->ptr = new block; else if (pp->ptr->v[pp->ptr->used - 1] == ntags) return 1; else if (pp->ptr->used >= BLOCK_SIZE) pp->ptr = new block(pp->ptr); pp->ptr->v[(pp->ptr->used)++] = ntags; return 1; }
const char *find_year(const char *start, const char *end, const char **endp) { for (;;) { while (start < end && !csdigit(*start)) start++; const char *ptr = start; if (start == end) break; while (ptr < end && csdigit(*ptr)) ptr++; if (ptr - start == 4 || ptr - start == 3 || (ptr - start == 2 && (start[0] >= '4' || (start[0] == '3' && start[1] >= '2')))) { *endp = ptr; return start; } start = ptr; } return 0; }
int font::scan_papersize(const char *p, const char **size, double *length, double *width) { double l, w; char lu[2], wu[2]; const char *pp = p; int test_file = 1; char line[255]; again: if (csdigit(*pp)) { if (sscanf(pp, "%lf%1[ipPc],%lf%1[ipPc]", &l, lu, &w, wu) == 4 && l > 0 && w > 0 && unit_scale(&l, lu[0]) && unit_scale(&w, wu[0])) { if (length) *length = l; if (width) *width = w; if (size) *size = "custom"; return 1; } } else { int i; for (i = 0; i < NUM_PAPERSIZES; i++) if (strcasecmp(papersizes[i].name, pp) == 0) { if (length) *length = papersizes[i].length; if (width) *width = papersizes[i].width; if (size) *size = papersizes[i].name; return 1; } if (test_file) { FILE *f = fopen(p, "r"); if (f) { fgets(line, 254, f); fclose(f); test_file = 0; char *linep = strchr(line, '\0'); // skip final newline, if any if (*(--linep) == '\n') *linep = '\0'; pp = line; goto again; } } } return 0; }
static const char *find_day(const char *start, const char *end, const char **endp) { for (;;) { while (start < end && !csdigit(*start)) start++; const char *ptr = start; if (start == end) break; while (ptr < end && csdigit(*ptr)) ptr++; if ((ptr - start == 1 && start[0] != '0') || (ptr - start == 2 && (start[0] == '1' || start[0] == '2' || (start[0] == '3' && start[1] <= '1') || (start[0] == '0' && start[1] != '0')))) { *endp = ptr; return start; } start = ptr; } return 0; }
map_init::map_init() { int i; for (i = 0; i < 256; i++) map[i] = csalnum(i) ? cmlower(i) : '\0'; for (i = 0; i < 256; i++) { if (cslower(i)) { inv_map[i][0] = i; inv_map[i][1] = cmupper(i); inv_map[i][2] = '\0'; } else if (csdigit(i)) { inv_map[i][0] = i; inv_map[i][1] = 0; } else inv_map[i][0] = '\0'; } }
static int atoh(unsigned int *result, const char * const s, const size_t length) { size_t i = 0; unsigned int val = 0; while ((i < length) && csxdigit(s[i])) { if (csdigit(s[i])) val = val*0x10 + (s[i]-'0'); else if (csupper(s[i])) val = val*0x10 + (s[i]-'A') + 10; else val = val*0x10 + (s[i]-'a') + 10; i++; } if (i != length) return 0; *result = val; return 1; }
const char *check_unicode_name(const char *u) { if (*u != 'u') return 0; const char *p = ++u; for (;;) { int val = 0; const char *start = p; for (;;) { // only uppercase hex digits allowed if (!csxdigit(*p)) return 0; if (csdigit(*p)) val = val*0x10 + (*p-'0'); else if (csupper(*p)) val = val*0x10 + (*p-'A'+10); else return 0; // biggest Unicode value is U+10FFFF if (val > 0x10FFFF) return 0; p++; if (*p == '\0' || *p == '_') break; } // surrogates not allowed if ((val >= 0xD800 && val <= 0xDBFF) || (val >= 0xDC00 && val <= 0xDFFF)) return 0; if (val > 0xFFFF) { if (*start == '0') // no leading zeros allowed if > 0xFFFF return 0; } else if (p - start != 4) // otherwise, check for exactly 4 hex digits return 0; if (*p == '\0') break; p++; } return u; }
const int *index_search_item::search1(const char **pp, const char *end) { while (*pp < end && !csalnum(**pp)) *pp += 1; if (*pp >= end) return 0; const char *start = *pp; while (*pp < end && csalnum(**pp)) *pp += 1; int len = *pp - start; if (len < header.shortest) return 0; if (len > header.truncate) len = header.truncate; int is_number = 1; for (int i = 0; i < len; i++) if (csdigit(start[i])) key_buffer[i] = start[i]; else { key_buffer[i] = cmlower(start[i]); is_number = 0; } if (is_number && !(len == 4 && start[0] == '1' && start[1] == '9')) return 0; unsigned hc = hash(key_buffer, len); if (common_words_table) { for (int h = hc % common_words_table_size; common_words_table[h]; --h) { if (strlen(common_words_table[h]) == (size_t)len && memcmp(common_words_table[h], key_buffer, len) == 0) return 0; if (h == 0) h = common_words_table_size; } } int li = table[int(hc % header.table_size)]; return li < 0 ? &minus_one : lists + li; }
void reference::compute_sort_key() { if (sort_fields.length() == 0) return; sort_fields += '\0'; const char *sf = sort_fields.contents(); while (*sf != '\0') { sort_key += SORT_SEP; char f = *sf++; int n = 1; if (*sf == '+') { n = INT_MAX; sf++; } else if (csdigit(*sf)) { char *ptr; long l = strtol(sf, &ptr, 10); if (l == 0 && ptr == sf) ; else { sf = ptr; if (l < 0) { n = 1; } else { n = int(l); } } } if (f == '.') sortify_label(label.contents(), label.length(), sort_key); else if (f == AUTHOR_FIELDS[0]) sortify_authors(n, sort_key); else sortify_field(f, n, sort_key); } sort_fields.set_length(sort_fields.length() - 1); }
format *process_format(table_input &in, options *opt, format *current_format = 0) { input_entry_format *list = 0; int c = in.get(); for (;;) { int pre_vline = 0; int got_format = 0; int got_period = 0; format_type t = FORMAT_LEFT; for (;;) { if (c == EOF) { error("end of input while processing format"); free_input_entry_format_list(list); return 0; } switch (c) { case 'n': case 'N': t = FORMAT_NUMERIC; got_format = 1; break; case 'a': case 'A': got_format = 1; t = FORMAT_ALPHABETIC; break; case 'c': case 'C': got_format = 1; t = FORMAT_CENTER; break; case 'l': case 'L': got_format = 1; t = FORMAT_LEFT; break; case 'r': case 'R': got_format = 1; t = FORMAT_RIGHT; break; case 's': case 'S': got_format = 1; t = FORMAT_SPAN; break; case '^': got_format = 1; t = FORMAT_VSPAN; break; case '_': case '-': // tbl also accepts this got_format = 1; t = FORMAT_HLINE; break; case '=': got_format = 1; t = FORMAT_DOUBLE_HLINE; break; case '.': got_period = 1; break; case '|': pre_vline++; break; case ' ': case '\t': case '\n': break; default: if (c == opt->tab_char) break; error("unrecognised format `%1'", char(c)); free_input_entry_format_list(list); return 0; } if (got_period) break; c = in.get(); if (got_format) break; } if (got_period) break; list = new input_entry_format(t, list); if (pre_vline) list->pre_vline = pre_vline; int success = 1; do { switch (c) { case 't': case 'T': c = in.get(); list->vertical_alignment = entry_modifier::TOP; break; case 'd': case 'D': c = in.get(); list->vertical_alignment = entry_modifier::BOTTOM; break; case 'u': case 'U': c = in.get(); list->stagger = 1; break; case 'z': case 'Z': c = in.get(); list->zero_width = 1; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int w = 0; do { w = w*10 + (c - '0'); c = in.get(); } while (c != EOF && csdigit(c)); list->separation = w; } break; case 'f': case 'F': do { c = in.get(); } while (c == ' ' || c == '\t'); if (c == EOF) { error("missing font name"); break; } if (c == '(') { for (;;) { c = in.get(); if (c == EOF || c == ' ' || c == '\t') { error("missing `)'"); break; } if (c == ')') { c = in.get(); break; } list->font += char(c); } } else { list->font = c; char cc = c; c = in.get(); if (!csdigit(cc) && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') { list->font += char(c); c = in.get(); } } break; case 'x': case 'X': do { c = in.get(); } while (c == ' ' || c == '\t'); if (c == EOF) { error("missing macro name"); break; } if (c == '(') { for (;;) { c = in.get(); if (c == EOF || c == ' ' || c == '\t') { error("missing `)'"); break; } if (c == ')') { c = in.get(); break; } list->macro += char(c); } } else { list->macro = c; char cc = c; c = in.get(); if (!csdigit(cc) && c != EOF && c != ' ' && c != '\t' && c != '.' && c != '\n') { list->macro += char(c); c = in.get(); } } break; case 'v': case 'V': c = in.get(); list->vertical_spacing.val = 0; list->vertical_spacing.inc = 0; if (c == '+' || c == '-') { list->vertical_spacing.inc = (c == '+' ? 1 : -1); c = in.get(); } if (c == EOF || !csdigit(c)) { error("`v' modifier must be followed by number"); list->vertical_spacing.inc = 0; } else { do { list->vertical_spacing.val *= 10; list->vertical_spacing.val += c - '0'; c = in.get(); } while (c != EOF && csdigit(c)); } if (list->vertical_spacing.val > MAX_VERTICAL_SPACING || list->vertical_spacing.val < -MAX_VERTICAL_SPACING) { error("unreasonable vertical spacing"); list->vertical_spacing.val = 0; list->vertical_spacing.inc = 0; } break; case 'p': case 'P': c = in.get(); list->point_size.val = 0; list->point_size.inc = 0; if (c == '+' || c == '-') { list->point_size.inc = (c == '+' ? 1 : -1); c = in.get(); } if (c == EOF || !csdigit(c)) { error("`p' modifier must be followed by number"); list->point_size.inc = 0; } else { do { list->point_size.val *= 10; list->point_size.val += c - '0'; c = in.get(); } while (c != EOF && csdigit(c)); } if (list->point_size.val > MAX_POINT_SIZE || list->point_size.val < -MAX_POINT_SIZE) { error("unreasonable point size"); list->point_size.val = 0; list->point_size.inc = 0; } break; case 'w': case 'W': c = in.get(); while (c == ' ' || c == '\t') c = in.get(); if (c == '(') { list->width = ""; c = in.get(); while (c != ')') { if (c == EOF || c == '\n') { error("missing `)'"); free_input_entry_format_list(list); return 0; } list->width += c; c = in.get(); } c = in.get(); } else { if (c == '+' || c == '-') { list->width = char(c); c = in.get(); } else list->width = ""; if (c == EOF || !csdigit(c)) error("bad argument for `w' modifier"); else { do { list->width += char(c); c = in.get(); } while (c != EOF && csdigit(c)); } } break; case 'e': case 'E': c = in.get(); list->equal++; break; case '|': c = in.get(); list->vline++; break; case 'B': case 'b': c = in.get(); list->font = "B"; break; case 'I': case 'i': c = in.get(); list->font = "I"; break; case ' ': case '\t': c = in.get(); break; default: if (c == opt->tab_char) c = in.get(); else success = 0; break; } } while (success); if (list->vline > 2) { 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) { 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; }
static int parse_term(units *v, int scale_indicator, int parenthesised, int rigid) { int negative = 0; for (;;) if (parenthesised && tok.space()) tok.next(); else if (tok.ch() == '+') tok.next(); else if (tok.ch() == '-') { tok.next(); negative = !negative; } else break; unsigned char c = tok.ch(); switch (c) { case '|': // | is not restricted to the outermost level // tbl uses this tok.next(); if (!parse_term(v, scale_indicator, parenthesised, rigid)) return 0; int tem; tem = (scale_indicator == 'v' ? curdiv->get_vertical_position().to_units() : curenv->get_input_line_position().to_units()); if (tem >= 0) { if (*v < INT_MIN + tem) { error("numeric overflow"); return 0; } } else { if (*v > INT_MAX + tem) { error("numeric overflow"); return 0; } } *v -= tem; if (negative) { if (*v == INT_MIN) { error("numeric overflow"); return 0; } *v = -*v; } return 1; case '(': tok.next(); c = tok.ch(); if (c == ')') { if (rigid) return 0; warning(WARN_SYNTAX, "empty parentheses"); tok.next(); *v = 0; return 1; } else if (c != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) { tok.next(); if (tok.ch() == ';') { tok.next(); scale_indicator = c; } else { error("expected `;' after scale-indicator (got %1)", tok.description()); return 0; } } else if (c == ';') { scale_indicator = 0; tok.next(); } if (!parse_expr(v, scale_indicator, 1, rigid)) return 0; tok.skip(); if (tok.ch() != ')') { if (rigid) return 0; warning(WARN_SYNTAX, "missing `)' (got %1)", tok.description()); } else tok.next(); if (negative) { if (*v == INT_MIN) { error("numeric overflow"); return 0; } *v = -*v; } return 1; case '.': *v = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *v = 0; do { if (*v > INT_MAX/10) { error("numeric overflow"); return 0; } *v *= 10; if (*v > INT_MAX - (int(c) - '0')) { error("numeric overflow"); return 0; } *v += c - '0'; tok.next(); c = tok.ch(); } while (csdigit(c)); break; case '/': case '*': case '%': case ':': case '&': case '>': case '<': case '=': warning(WARN_SYNTAX, "empty left operand"); *v = 0; return rigid ? 0 : 1; default: warning(WARN_NUMBER, "numeric expression expected (got %1)", tok.description()); return 0; } int divisor = 1; if (tok.ch() == '.') { tok.next(); for (;;) { c = tok.ch(); if (!csdigit(c)) break; // we may multiply the divisor by 254 later on if (divisor <= INT_MAX/2540 && *v <= (INT_MAX - 9)/10) { *v *= 10; *v += c - '0'; divisor *= 10; } tok.next(); } } int si = scale_indicator; int do_next = 0; if ((c = tok.ch()) != 0 && strchr(SCALE_INDICATOR_CHARS, c) != 0) { switch (scale_indicator) { case 'z': if (c != 'u' && c != 'z') { warning(WARN_SCALE, "only `z' and `u' scale indicators valid in this context"); break; } si = c; break; case 0: warning(WARN_SCALE, "scale indicator invalid in this context"); break; case 'u': si = c; break; default: if (c == 'z') { warning(WARN_SCALE, "`z' scale indicator invalid in this context"); break; } si = c; break; } // Don't do tok.next() here because the next token might be \s, which // would affect the interpretation of m. do_next = 1; } switch (si) { case 'i': *v = scale(*v, units_per_inch, divisor); break; case 'c': *v = scale(*v, units_per_inch*100, divisor*254); break; case 0: case 'u': if (divisor != 1) *v /= divisor; break; case 'f': *v = scale(*v, 65536, divisor); break; case 'p': *v = scale(*v, units_per_inch, divisor*72); break; case 'P': *v = scale(*v, units_per_inch, divisor*6); break; case 'm': { // Convert to hunits so that with -Tascii `m' behaves as in nroff. hunits em = curenv->get_size(); *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor); } break; case 'M': { hunits em = curenv->get_size(); *v = scale(*v, em.is_zero() ? hresolution : em.to_units(), divisor*100); } break; case 'n': { // Convert to hunits so that with -Tascii `n' behaves as in nroff. hunits en = curenv->get_size()/2; *v = scale(*v, en.is_zero() ? hresolution : en.to_units(), divisor); } break; case 'v': *v = scale(*v, curenv->get_vertical_spacing().to_units(), divisor); break; case 's': while (divisor > INT_MAX/(sizescale*72)) { divisor /= 10; *v /= 10; } *v = scale(*v, units_per_inch, divisor*sizescale*72); break; case 'z': *v = scale(*v, sizescale, divisor); break; default: assert(0); } if (do_next) tok.next(); if (negative) { if (*v == INT_MIN) { error("numeric overflow"); return 0; } *v = -*v; } return 1; }
void reference::output(FILE *fp) { fputs(".]-\n", fp); for (int i = 0; i < 256; i++) if (field_index[i] != NULL_FIELD_INDEX && i != annotation_field) { string &f = field[field_index[i]]; if (!csdigit(i)) { int j = reverse_fields.search(i); if (j >= 0) { int n; int len = reverse_fields.length(); if (++j < len && csdigit(reverse_fields[j])) { n = reverse_fields[j] - '0'; for (++j; j < len && csdigit(reverse_fields[j]); j++) // should check for overflow n = n*10 + reverse_fields[j] - '0'; } else n = INT_MAX; reverse_names(f, n); } } int is_multiple = join_fields(f) > 0; if (capitalize_fields.search(i) >= 0) capitalize_field(f); if (memchr(f.contents(), '\n', f.length()) == 0) { fprintf(fp, ".ds [%c ", i); if (f[0] == ' ' || f[0] == '\\' || f[0] == '"') putc('"', fp); put_string(f, fp); putc('\n', fp); } else { fprintf(fp, ".de [%c\n", i); put_string(f, fp); fputs("..\n", fp); } if (i == 'P') { int multiple_pages = 0; const char *s = f.contents(); const char *end = f.contents() + f.length(); for (;;) { const char *token_start = s; if (!get_token(&s, end)) break; const token_info *ti = lookup_token(token_start, s); if (ti->is_hyphen() || ti->is_range_sep()) { multiple_pages = 1; break; } } fprintf(fp, ".nr [P %d\n", multiple_pages); } else if (i == 'E') fprintf(fp, ".nr [E %d\n", is_multiple); } for (const char *p = "TAO"; *p; p++) { int fi = field_index[(unsigned char)*p]; if (fi != NULL_FIELD_INDEX) { string &f = field[fi]; fprintf(fp, ".nr [%c %d\n", *p, is_terminated(f.contents(), f.contents() + f.length())); } } int t = classify(); fprintf(fp, ".][ %d %s\n", t, reference_types[t]); if (annotation_macro.length() > 0 && annotation_field >= 0 && field_index[annotation_field] != NULL_FIELD_INDEX) { putc('.', fp); put_string(annotation_macro, fp); putc('\n', fp); put_string(field[field_index[annotation_field]], fp); } }
int get_token(int lookup_flag) { context_buffer.clear(); for (;;) { int n = 0; int bol = input_stack::bol(); int c = input_stack::get_char(); if (bol && c == command_char) { token_buffer.clear(); token_buffer += c; // the newline is not part of the token for (;;) { c = input_stack::peek_char(); if (c == EOF || c == '\n') break; input_stack::get_char(); token_buffer += char(c); } context_buffer = token_buffer; return COMMAND_LINE; } switch (c) { case EOF: return EOF; case ' ': case '\t': break; case '\\': { int d = input_stack::peek_char(); if (d != '\n') { context_buffer = '\\'; return '\\'; } input_stack::get_char(); break; } case '#': do { c = input_stack::get_char(); } while (c != '\n' && c != EOF); if (c == '\n') context_buffer = '\n'; return c; case '"': context_buffer = '"'; token_buffer.clear(); for (;;) { c = input_stack::get_char(); if (c == '\\') { context_buffer += '\\'; c = input_stack::peek_char(); if (c == '"') { input_stack::get_char(); token_buffer += '"'; context_buffer += '"'; } else token_buffer += '\\'; } else if (c == '\n') { error("newline in string"); break; } else if (c == EOF) { error("missing `\"'"); break; } else if (c == '"') { context_buffer += '"'; break; } else { context_buffer += char(c); token_buffer += char(c); } } return TEXT; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { int overflow = 0; n = 0; for (;;) { if (n > (INT_MAX - 9)/10) { overflow = 1; break; } n *= 10; n += c - '0'; context_buffer += char(c); c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; c = input_stack::get_char(); } token_double = n; if (overflow) { for (;;) { token_double *= 10.0; token_double += c - '0'; context_buffer += char(c); c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; c = input_stack::get_char(); } // if somebody asks for 1000000000000th, we will silently // give them INT_MAXth double temp = token_double; // work around gas 1.34/sparc bug if (token_double > INT_MAX) n = INT_MAX; else n = int(temp); } } switch (c) { case 'i': case 'I': context_buffer += char(c); input_stack::get_char(); return NUMBER; case '.': { context_buffer += '.'; input_stack::get_char(); got_dot: double factor = 1.0; for (;;) { c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; input_stack::get_char(); context_buffer += char(c); factor /= 10.0; if (c != '0') token_double += factor*(c - '0'); } if (c != 'e' && c != 'E') { if (c == 'i' || c == 'I') { context_buffer += char(c); input_stack::get_char(); } return NUMBER; } } // fall through case 'e': case 'E': { int echar = c; input_stack::get_char(); c = input_stack::peek_char(); int sign = '+'; if (c == '+' || c == '-') { sign = c; input_stack::get_char(); c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) { input_stack::push_back(sign); input_stack::push_back(echar); return NUMBER; } context_buffer += char(echar); context_buffer += char(sign); } else { if (c == EOF || !csdigit(c)) { input_stack::push_back(echar); return NUMBER; } context_buffer += char(echar); } input_stack::get_char(); context_buffer += char(c); n = c - '0'; for (;;) { c = input_stack::peek_char(); if (c == EOF || !csdigit(c)) break; input_stack::get_char(); context_buffer += char(c); n = n*10 + (c - '0'); } if (sign == '-') n = -n; if (c == 'i' || c == 'I') { context_buffer += char(c); input_stack::get_char(); } token_double *= pow(10.0, n); return NUMBER; } case 'n': input_stack::get_char(); c = input_stack::peek_char(); if (c == 'd') { input_stack::get_char(); token_int = n; context_buffer += "nd"; return ORDINAL; } input_stack::push_back('n'); return NUMBER; case 'r': input_stack::get_char(); c = input_stack::peek_char(); if (c == 'd') { input_stack::get_char(); token_int = n; context_buffer += "rd"; return ORDINAL; } input_stack::push_back('r'); return NUMBER; case 't': input_stack::get_char(); c = input_stack::peek_char(); if (c == 'h') { input_stack::get_char(); token_int = n; context_buffer += "th"; return ORDINAL; } input_stack::push_back('t'); return NUMBER; case 's': input_stack::get_char(); c = input_stack::peek_char(); if (c == 't') { input_stack::get_char(); token_int = n; context_buffer += "st"; return ORDINAL; } input_stack::push_back('s'); return NUMBER; default: return NUMBER; } break; case '\'': { c = input_stack::peek_char(); if (c == 't') { input_stack::get_char(); c = input_stack::peek_char(); if (c == 'h') { input_stack::get_char(); context_buffer = "'th"; return TH; } else input_stack::push_back('t'); } context_buffer = "'"; return '\''; } case '.': { c = input_stack::peek_char(); if (c != EOF && csdigit(c)) { n = 0; token_double = 0.0; context_buffer = '.'; goto got_dot; } return get_token_after_dot(c); } case '<': c = input_stack::peek_char(); if (c == '-') { input_stack::get_char(); c = input_stack::peek_char(); if (c == '>') { input_stack::get_char(); context_buffer = "<->"; return DOUBLE_ARROW_HEAD; } context_buffer = "<-"; return LEFT_ARROW_HEAD; } else if (c == '=') { input_stack::get_char(); context_buffer = "<="; return LESSEQUAL; } context_buffer = "<"; return '<'; case '-': c = input_stack::peek_char(); if (c == '>') { input_stack::get_char(); context_buffer = "->"; return RIGHT_ARROW_HEAD; } context_buffer = "-"; return '-'; case '!': c = input_stack::peek_char(); if (c == '=') { input_stack::get_char(); context_buffer = "!="; return NOTEQUAL; } context_buffer = "!"; return '!'; case '>': c = input_stack::peek_char(); if (c == '=') { input_stack::get_char(); context_buffer = ">="; return GREATEREQUAL; } context_buffer = ">"; return '>'; case '=': c = input_stack::peek_char(); if (c == '=') { input_stack::get_char(); context_buffer = "=="; return EQUALEQUAL; } context_buffer = "="; return '='; case '&': c = input_stack::peek_char(); if (c == '&') { input_stack::get_char(); context_buffer = "&&"; return ANDAND; } context_buffer = "&"; return '&'; case '|': c = input_stack::peek_char(); if (c == '|') { input_stack::get_char(); context_buffer = "||"; return OROR; } context_buffer = "|"; return '|'; default: if (c != EOF && csalpha(c)) { token_buffer.clear(); token_buffer = c; for (;;) { c = input_stack::peek_char(); if (c == EOF || (!csalnum(c) && c != '_')) break; input_stack::get_char(); token_buffer += char(c); } int tok = lookup_keyword(token_buffer.contents(), token_buffer.length()); if (tok != 0) { context_buffer = token_buffer; return tok; } char *def = 0; if (lookup_flag) { token_buffer += '\0'; def = macro_table.lookup(token_buffer.contents()); token_buffer.set_length(token_buffer.length() - 1); if (def) { if (c == '(') { input_stack::get_char(); interpolate_macro_with_args(def); } else input_stack::push(new macro_input(def)); } } if (!def) { context_buffer = token_buffer; if (csupper(token_buffer[0])) return LABEL; else return VARIABLE; } } else { context_buffer = char(c); return (unsigned char)c; } break; } } }