From a3f4d23f93436ac81e1a45ace99039efcc3880bd Mon Sep 17 00:00:00 2001 From: Werner LEMBERG Date: Mon, 27 Sep 2004 06:09:40 +0000 Subject: [PATCH] Fix \$@ and \$* to handle any number of arguments. * src/roff/troff/input.h (BEGIN_QUOTE, END_QUOTE): New special characters. * src/roff/troff/input.cpp (input_iterator::internal_level): Removed. (input_stack): New member functions `increase_level' and `decrease_level'. (input_stack::get_level): Don't use `internal_level'. (get_copy, token::next): Handle BEGIN_QUOTE and END_QUOTE. (end_quote_iterator): Completely removed. (interpolate_arg): Build string for \$@ and \$* which is then pushed onto the input stack. --- ChangeLog | 17 ++++++++++ src/roff/troff/input.cpp | 87 +++++++++++++++++++++++++++++++----------------- src/roff/troff/input.h | 4 +++ 3 files changed, 78 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 418925fd..8dca2588 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2004-09-26 Werner LEMBERG + + Fix \$@ and \$* to handle any number of arguments. + + * src/roff/troff/input.h (BEGIN_QUOTE, END_QUOTE): New special + characters. + + * src/roff/troff/input.cpp (input_iterator::internal_level): + Removed. + (input_stack): New member functions `increase_level' and + `decrease_level'. + (input_stack::get_level): Don't use `internal_level'. + (get_copy, token::next): Handle BEGIN_QUOTE and END_QUOTE. + (end_quote_iterator): Completely removed. + (interpolate_arg): Build string for \$@ and \$* which is then + pushed onto the input stack. + 2004-09-23 Keith Marshall * tmac/groff_ms.man, doc/groff.texinfo: Document changes from diff --git a/src/roff/troff/input.cpp b/src/roff/troff/input.cpp index 5ad1c745..70340d7c 100644 --- a/src/roff/troff/input.cpp +++ b/src/roff/troff/input.cpp @@ -214,7 +214,6 @@ private: virtual int next_file(FILE *, const char *) { return 0; } virtual void shift(int) {} virtual int is_boundary() {return 0; } - virtual int internal_level() { return 0; } virtual int is_file() { return 0; } virtual int is_macro() { return 0; } virtual void save_compatible_flag(int) {} @@ -416,6 +415,8 @@ public: static int is_return_boundary(); static void remove_boundary(); static int get_level(); + static void increase_level(); + static void decrease_level(); static void clear(); static void pop_macro(); static void save_compatible_flag(int); @@ -436,7 +437,17 @@ int input_stack::limit = DEFAULT_INPUT_STACK_LIMIT; inline int input_stack::get_level() { - return level + top->internal_level(); + return level; +} + +inline void input_stack::increase_level() +{ + level++; +} + +inline void input_stack::decrease_level() +{ + level--; } inline int input_stack::get(node **np) @@ -850,6 +861,14 @@ static int get_copy(node **nd, int defining) compatible_flag = input_stack::get_compatible_flag(); continue; } + if (c == BEGIN_QUOTE) { + input_stack::increase_level(); + continue; + } + if (c == END_QUOTE) { + input_stack::decrease_level(); + continue; + } if (c == ESCAPE_NEWLINE) { if (defining) return c; @@ -1584,6 +1603,12 @@ void token::next() case POP_GROFFCOMP_MODE: compatible_flag = input_stack::get_compatible_flag(); continue; + case BEGIN_QUOTE: + input_stack::increase_level(); + continue; + case END_QUOTE: + input_stack::decrease_level(); + continue; case EOF: type = TOKEN_EOF; return; @@ -4029,26 +4054,6 @@ static void interpolate_string_with_args(symbol s) } } -/* This class is used for the implementation of \$@. It is used for -each of the closing double quotes. It artificially increases the -input level by 2, so that the closing double quote will appear to have -the same input level as the opening quote. */ - -class end_quote_iterator : public input_iterator { - unsigned char buf[1]; -public: - end_quote_iterator(); - ~end_quote_iterator() { } - int internal_level() { return 2; } -}; - -end_quote_iterator::end_quote_iterator() -{ - buf[0] = '"'; - ptr = buf; - eptr = buf + 1; -} - static void interpolate_arg(symbol nm) { const char *s = nm.contents(); @@ -4057,17 +4062,39 @@ static void interpolate_arg(symbol nm) else if (s[1] == 0 && csdigit(s[0])) input_stack::push(input_stack::get_arg(s[0] - '0')); else if (s[0] == '*' && s[1] == '\0') { - for (int i = input_stack::nargs(); i > 0; i--) { - input_stack::push(input_stack::get_arg(i)); - if (i != 1) - input_stack::push(make_temp_iterator(" ")); + int limit = input_stack::nargs(); + string args; + for (int i = 1; i <= limit; i++) { + input_iterator *p = input_stack::get_arg(i); + int c; + while ((c = p->get(0)) != EOF) + args += c; + if (i != limit) + args += ' '; + } + if (limit > 0) { + args += '\0'; + input_stack::push(make_temp_iterator(args.contents())); } } else if (s[0] == '@' && s[1] == '\0') { - for (int i = input_stack::nargs(); i > 0; i--) { - input_stack::push(new end_quote_iterator); - input_stack::push(input_stack::get_arg(i)); - input_stack::push(make_temp_iterator(i == 1 ? "\"" : " \"")); + int limit = input_stack::nargs(); + string args; + for (int i = 1; i <= limit; i++) { + args += '"'; + args += BEGIN_QUOTE; + input_iterator *p = input_stack::get_arg(i); + int c; + while ((c = p->get(0)) != EOF) + args += c; + args += END_QUOTE; + args += '"'; + if (i != limit) + args += ' '; + } + if (limit > 0) { + args += '\0'; + input_stack::push(make_temp_iterator(args.contents())); } } else { diff --git a/src/roff/troff/input.h b/src/roff/troff/input.h index 59f9e005..aaaa70bd 100644 --- a/src/roff/troff/input.h +++ b/src/roff/troff/input.h @@ -57,6 +57,8 @@ const int ESCAPE_COLON = 0210; const int PUSH_GROFF_MODE = 0211; const int PUSH_COMP_MODE = 0212; const int POP_GROFFCOMP_MODE = 0213; +const int BEGIN_QUOTE = 0214; +const int END_QUOTE = 0215; #else /* IS_EBCDIC_HOST */ @@ -94,6 +96,8 @@ const int ESCAPE_COLON = 070; const int PUSH_GROFF_MODE = 071; const int PUSH_COMP_MODE = 072; const int POP_GROFFCOMP_MODE = 073; +const int BEGIN_QUOTE = 074; +const int END_QUOTE = 075; #endif /* IS_EBCDIC_HOST */ -- 2.11.4.GIT