diff options
Diffstat (limited to 'contrib/groff/src/roff/troff/input.cc')
-rw-r--r-- | contrib/groff/src/roff/troff/input.cc | 191 |
1 files changed, 159 insertions, 32 deletions
diff --git a/contrib/groff/src/roff/troff/input.cc b/contrib/groff/src/roff/troff/input.cc index 982e5bd..54aaa3f 100644 --- a/contrib/groff/src/roff/troff/input.cc +++ b/contrib/groff/src/roff/troff/input.cc @@ -73,6 +73,8 @@ extern "C" { // initial size of buffer for reading names; expanded as necessary #define ABUF_SIZE 16 +extern "C" const char *Version_string; + #ifdef COLUMN void init_column_requests(); #endif /* COLUMN */ @@ -106,7 +108,7 @@ static void disable_warning(const char *); static int escape_char = '\\'; static symbol end_macro_name; static symbol blank_line_macro_name; -int compatible_flag = 0; +static int compatible_flag = 0; int ascii_output_flag = 0; int suppress_output_flag = 0; int is_html = 0; @@ -133,6 +135,7 @@ static void interpolate_arg(symbol); static request_or_macro *lookup_request(symbol); static int get_delim_number(units *, int); static int get_delim_number(units *, int, units); +static symbol get_delim_file_name(); static int get_line_arg(units *res, int si, charinfo **cp); static int read_size(int *); static symbol get_delim_name(); @@ -206,6 +209,8 @@ private: virtual int internal_level() { return 0; } virtual int is_file() { return 0; } virtual int is_macro() { return 0; } + virtual void save_compatible_flag(int) {} + virtual int get_compatible_flag() { return 0; } }; input_iterator::input_iterator() @@ -406,6 +411,8 @@ public: static int get_level(); static void clear(); static void pop_macro(); + static void save_compatible_flag(int); + static int get_compatible_flag(); static int limit; private: @@ -626,6 +633,16 @@ void input_stack::pop_macro() add_return_boundary(); } +inline void input_stack::save_compatible_flag(int f) +{ + top->save_compatible_flag(f); +} + +inline int input_stack::get_compatible_flag() +{ + return top->get_compatible_flag(); +} + void backtrace_request() { input_stack::backtrace_all(); @@ -1272,6 +1289,13 @@ void token::next() if (cc != escape_char || escape_char == 0) { handle_normal_char: switch(cc) { + case COMPATIBLE_SAVE: + input_stack::save_compatible_flag(compatible_flag); + compatible_flag = 0; + continue; + case COMPATIBLE_RESTORE: + compatible_flag = input_stack::get_compatible_flag(); + continue; case EOF: type = TOKEN_EOF; return; @@ -2049,14 +2073,14 @@ static void trapping_blank_line() void do_request() { - int saved_compatible_flag = compatible_flag; + int old_compatible_flag = compatible_flag; compatible_flag = 0; symbol nm = get_name(); if (nm.is_null()) skip_line(); else interpolate_macro(nm); - compatible_flag = saved_compatible_flag; + compatible_flag = old_compatible_flag; } inline int possibly_handle_first_page_transition() @@ -2701,6 +2725,7 @@ class string_iterator : public input_iterator { char_block *bp; int count; // of characters remaining node *nd; + int saved_compatible_flag; protected: symbol nm; string_iterator(); @@ -2710,6 +2735,8 @@ public: int peek(); int get_location(int, const char **, int *); void backtrace(); + void save_compatible_flag(int f) { saved_compatible_flag = f; } + int get_compatible_flag() { return saved_compatible_flag; } }; string_iterator::string_iterator(const macro &m, const char *p, symbol s) @@ -3447,11 +3474,12 @@ void handle_initial_title() static symbol dot_symbol("."); enum define_mode { DEFINE_NORMAL, DEFINE_APPEND, DEFINE_IGNORE }; +enum calling_mode { CALLING_NORMAL, CALLING_INDIRECT, CALLING_DISABLE_COMP }; -void do_define_macro(define_mode mode, int indirect) +void do_define_macro(define_mode mode, calling_mode calling) { symbol nm, term; - if (indirect) { + if (calling == CALLING_INDIRECT) { symbol temp1 = get_name(1); if (temp1.is_null()) { skip_line(); @@ -3497,6 +3525,8 @@ void do_define_macro(define_mode mode, int indirect) mac = *mm; } int bol = 1; + if (calling == CALLING_DISABLE_COMP) + mac.append(COMPATIBLE_SAVE); for (;;) { while (c == ESCAPE_NEWLINE) { if (mode == DEFINE_NORMAL || mode == DEFINE_APPEND) @@ -3505,7 +3535,7 @@ void do_define_macro(define_mode mode, int indirect) } if (bol && c == '.') { const char *s = term.contents(); - int d; + int d = 0; // see if it matches term int i; for (i = 0; s[i] != 0; i++) { @@ -3517,25 +3547,27 @@ void do_define_macro(define_mode mode, int indirect) && ((i == 2 && compatible_flag) || (d = get_copy(&n)) == ' ' || d == '\n')) { // we found it - if (d == '\n') - tok.make_newline(); - else - tok.make_space(); - if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) { - if (!mm) { - mm = new macro; - request_dictionary.define(nm, mm); - } - *mm = mac; - } - if (term != dot_symbol) { - ignoring = 0; - interpolate_macro(term); - } - else - skip_line(); - return; - } + if (d == '\n') + tok.make_newline(); + else + tok.make_space(); + if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) { + if (!mm) { + mm = new macro; + request_dictionary.define(nm, mm); + } + if (calling == CALLING_DISABLE_COMP) + mac.append(COMPATIBLE_RESTORE); + *mm = mac; + } + if (term != dot_symbol) { + ignoring = 0; + interpolate_macro(term); + } + else + skip_line(); + return; + } if (mode == DEFINE_APPEND || mode == DEFINE_NORMAL) { mac.append(c); for (int j = 0; j < i; j++) @@ -3575,23 +3607,33 @@ void do_define_macro(define_mode mode, int indirect) void define_macro() { - do_define_macro(DEFINE_NORMAL, 0); + do_define_macro(DEFINE_NORMAL, CALLING_NORMAL); +} + +void define_nocomp_macro() +{ + do_define_macro(DEFINE_NORMAL, CALLING_DISABLE_COMP); } void define_indirect_macro() { - do_define_macro(DEFINE_NORMAL, 1); + do_define_macro(DEFINE_NORMAL, CALLING_INDIRECT); } void append_macro() { - do_define_macro(DEFINE_APPEND, 0); + do_define_macro(DEFINE_APPEND, CALLING_NORMAL); +} + +void append_nocomp_macro() +{ + do_define_macro(DEFINE_APPEND, CALLING_DISABLE_COMP); } void ignore() { ignoring = 1; - do_define_macro(DEFINE_IGNORE, 0); + do_define_macro(DEFINE_IGNORE, CALLING_NORMAL); ignoring = 0; } @@ -3954,6 +3996,11 @@ static int read_size(int *x) if (!bad) { switch (inc) { case 0: + if (val == 0) { + // special case -- \s[0] and \s0 means to revert to previous size + *x = 0; + return 1; + } *x = val; break; case 1: @@ -3965,6 +4012,11 @@ static int read_size(int *x) default: assert(0); } + if (*x <= 0) { + warning(WARN_RANGE, + "\\s request results in non-positive point size; set to 1"); + *x = 1; + } return 1; } else { @@ -4033,6 +4085,65 @@ static symbol get_delim_name() } } +static symbol get_delim_file_name() +{ + token start; + start.next(); + if (start.eof()) { + error("end of input at start of delimited file name"); + return NULL_SYMBOL; + } + if (start.newline()) { + error("can't delimit file name with a newline"); + return NULL_SYMBOL; + } + int start_level = input_stack::get_level(); + char abuf[ABUF_SIZE]; + char *buf = abuf; + int buf_size = ABUF_SIZE; + int i = 0; + for (;;) { + if (i + 1 > buf_size) { + if (buf == abuf) { + buf = new char[ABUF_SIZE*2]; + memcpy(buf, abuf, buf_size); + buf_size = ABUF_SIZE*2; + } + else { + char *old_buf = buf; + buf = new char[buf_size*2]; + memcpy(buf, old_buf, buf_size); + buf_size *= 2; + a_delete old_buf; + } + } + tok.next(); + if (tok.ch() == ']' && input_stack::get_level() == start_level) + break; + if ((buf[i] = tok.ch()) == 0) { + error("missing delimiter (got %1)", tok.description()); + if (buf != abuf) + a_delete buf; + return NULL_SYMBOL; + } + i++; + } + buf[i] = '\0'; + if (buf == abuf) { + if (i == 0) { + error("empty delimited file name"); + return NULL_SYMBOL; + } + else + return symbol(buf); + } + else { + symbol s(buf); + a_delete buf; + return s; + } +} + // Implement \R static void do_register() @@ -4273,6 +4384,14 @@ node *do_suppress() { tok.next(); int c = tok.ch(); + if (c != '[') { + error("argument(s) of \\O must be enclosed in brackets (got %1)", + char(c)); + return 0; + } + tok.next(); + c = tok.ch(); + tok.next(); switch (c) { case '0': if (begin_level == 1) @@ -4293,7 +4412,12 @@ node *do_suppress() begin_level--; break; case '5': { - symbol filename = get_delim_name(); + symbol filename = get_delim_file_name(); + tok.next(); + if (filename.is_null()) { + error("missing filename as second argument to \\O"); + return 0; + } if (begin_level == 1) return new suppress_node(filename, 'i'); return 0; @@ -6034,12 +6158,14 @@ struct string_list { string_list(const char *ss) : s(ss), next(0) {} }; +#if 0 static void prepend_string(const char *s, string_list **p) { string_list *l = new string_list(s); l->next = *p; *p = l; } +#endif static void add_string(const char *s, string_list **p) { @@ -6095,7 +6221,6 @@ int main(int argc, char **argv) switch(c) { case 'v': { - extern const char *Version_string; printf("GNU troff (groff) version %s\n", Version_string); exit(0); break; @@ -6346,7 +6471,9 @@ void init_input_requests() init_request("as", append_string); init_request("de", define_macro); init_request("dei", define_indirect_macro); + init_request("de1", define_nocomp_macro); init_request("am", append_macro); + init_request("am1", append_nocomp_macro); init_request("ig", ignore); init_request("rm", remove_macro); init_request("rn", rename_macro); @@ -6638,7 +6765,7 @@ static struct { static int lookup_warning(const char *name) { - for (int i = 0; + for (unsigned int i = 0; i < sizeof(warning_table)/sizeof(warning_table[0]); i++) if (strcmp(name, warning_table[i].name) == 0) |