diff options
author | wlemb <wlemb> | 2002-06-29 21:44:31 +0000 |
---|---|---|
committer | wlemb <wlemb> | 2002-06-29 21:44:31 +0000 |
commit | b1e38e988e773d47711d8cea364bec4c50bf6a12 (patch) | |
tree | 2569353325c78e3399596ab2844d43f52657bab1 | |
parent | 9d91f66adb9ba252b72646a961f95d3d26af5abe (diff) | |
download | groff-b1e38e988e773d47711d8cea364bec4c50bf6a12.tar.gz |
Implementation of string arguments of the form \*[foo arg1 arg2 ...]
* src/roff/troff/input.cc (have_string_arg): New global variable.
(read_mode): New enumeration.
(read_escape_name): Use it. Update all calls.
(read_long_escape_name): Use it. Update all calls.
Set have_string_arg if appropriate.
(get_char_for_escape_name): Add parameter for handling space
character.
(interpolate_string_with_args, decode_string_args): New functions.
(get_copy, token::next): Call it if necessary.
(interpolate_string): Fix error message.
* NEWS, doc/groff.texinfo, man/groff.man, man/groff_diff.man:
Document it.
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | doc/groff.texinfo | 43 | ||||
-rw-r--r-- | man/groff.man | 46 | ||||
-rw-r--r-- | man/groff_diff.man | 26 | ||||
-rw-r--r-- | src/roff/troff/input.cc | 130 |
6 files changed, 205 insertions, 64 deletions
@@ -1,3 +1,21 @@ +2002-06-29 Werner LEMBERG <wl@gnu.org> + + Implementation of string arguments of the form \*[foo arg1 arg2 ...] + + * src/roff/troff/input.cc (have_string_arg): New global variable. + (read_mode): New enumeration. + (read_escape_name): Use it. Update all calls. + (read_long_escape_name): Use it. Update all calls. + Set have_string_arg if appropriate. + (get_char_for_escape_name): Add parameter for handling space + character. + (interpolate_string_with_args, decode_string_args): New functions. + (get_copy, token::next): Call it if necessary. + (interpolate_string): Fix error message. + + * NEWS, doc/groff.texinfo, man/groff.man, man/groff_diff.man: + Document it. + 2002-06-24 Bernd Warken <bwarken@mayn.de> * man/groff_tmac.man: Updated and extended. @@ -60,6 +60,12 @@ o Latin-1 character 181 (PS name `mu', Unicode name U+00B5 MICRO SIGN) has o -Tutf8 is now available on EBCDIC hosts. +o Strings can take arguments, using this syntax: \*[foo arg1 arg2 ...]. + Example: + + .ds xxx This is a \\$1 test. + \*[xxx nice] + o It is now possible to have whitespace between the first and second dot (or the name of the ending macro) to end a macro definition. Example: diff --git a/doc/groff.texinfo b/doc/groff.texinfo index 099b7c86..2f79d13a 100644 --- a/doc/groff.texinfo +++ b/doc/groff.texinfo @@ -772,6 +772,8 @@ The section on the @file{man} macro package is partly based on Susan@w{ }G.@: Kleinmann's @file{groff_man} manual page written for the Debian GNU/Linux system. +Larry Kollar contributed the section in the @file{ms} macro package. + @c ===================================================================== @@ -5370,7 +5372,7 @@ is returned. The following lists some built-in registers which are not described elsewhere in this manual. Any register which begins with a @samp{.} is read-only. A complete listing of all built-in registers can be found in -@ref{Register Index}. +appendix@w{ }@ref{Register Index}. @table @code @item .F @@ -8998,21 +9000,28 @@ even this is a read-write string variable). @DefreqItem {ds1, name [@Var{string}]} @DefescItem {\\*, , n, } @DefescItem {\\*, @lparen{}, nm, } -@DefescListEnd {\\*, @lbrack{}, name, @rbrack{}} +@DefescListEnd {\\*, @lbrack{}, name arg1 arg2 @dots{}, @rbrack{}} @cindex string interpolation (@code{\*}) @cindex string expansion (@code{\*}) @cindex interpolation of strings (@code{\*}) @cindex expansion of strings (@code{\*}) +@cindex string arguments +@cindex arguments, of strings Define and access a string variable @var{name} (one-character name@w{ }@var{n}, two-character name @var{nm}). If @var{name} already exists, -@code{ds} overwrites the previous definition. +@code{ds} overwrites the previous definition. Only the syntax form +using brackets can take arguments which are handled identically to +macro arguments; the single exception is that a closing bracket as an +argument must be enclosed in double quotes. @xref{Request Arguments}, +and @ref{Parameters}. Example: @Example -.ds UX \s-1UNIX\s0\u\s-3tm\s0\d +.ds foo a \\$1 test . -The \*(UX Operating System +This is \*[foo nice]. + @result{} This is a nice test. @endExample The @code{\*} escape @dfn{interpolates} (expands in-place) a @@ -9117,8 +9126,7 @@ This is @result{} This is a funny test. @endExample -Diversions and boxes can be also called with string syntax. It is not -possible to pass arguments to a macro if called with @code{\*}. +Diversions and boxes can be also called with string syntax. Another consequence is that you can copy one-line diversions or boxes to a string. @@ -9751,9 +9759,9 @@ Exit a macro, immediately returning to the caller. @cindex @code{\*}, when reading text for a macro @cindex @code{\\}, when reading text for a macro @cindex \@key{RET}, when reading text for a macro -When @code{gtroff} reads in the text for a macro or diversion, it copies -the text (including request lines, but excluding escapes) into an -internal buffer. Escapes are converted into an internal form, +When @code{gtroff} reads in the text for a macro, string, or diversion, +it copies the text (including request lines, but excluding escapes) into +an internal buffer. Escapes are converted into an internal form, except for @code{\n}, @code{\$}, @code{\*}, @code{\\} and @code{\@key{RET}} which are evaluated and inserted into the text where the escape was located. This is known as @dfn{copy-in} mode or @@ -9782,11 +9790,13 @@ The following example prints the numbers 20 and@w{ }10: @subsection Parameters @cindex parameters -The arguments to a macro can be examined using a variety of escapes. +The arguments to a macro or string can be examined using a variety of +escapes. @Defreg {.$} @cindex number of arguments register (@code{.$}) -The number of arguments in a macro. This is a read-only number register. +The number of arguments passed to a macro or string. This is a read-only +number register. @endDefreg Any individual argument can be retrieved with one of the following @@ -9802,9 +9812,9 @@ Retrieve the @var{n}@dmn{th}, @var{nn}@dmn{th} or @var{nnn}@dmn{th} argument. As usual, the first form only accepts a single number (larger than zero), the second a two-digit number (larger or equal to@w{ }10), and the third any positive integer value (larger -than zero). Macros can have an unlimited number of arguments. Note -that due to copy-in mode, use two backslashes on these in actual use to -prevent interpolation until the macro is actually invoked. +than zero). Macros and strings can have an unlimited number of arguments. +Note that due to copy-in mode, use two backslashes on these in actual use +to prevent interpolation until the macro is actually invoked. @endDefesc @Defreq {shift, [@Var{n}]} @@ -9902,7 +9912,8 @@ Here a primitive solution for a two-column macro. @endExample @Example .de 2c-trap -. ie \\n[right-side] \@{\. nr right-side 0 +. ie \\n[right-side] \@{\ +. nr right-side 0 . po -(\\n[column-length]u + \\n[column-gap]u) . \" remove trap . wh -\\n[bottom-margin]u diff --git a/man/groff.man b/man/groff.man index 008bab74..1e9128db 100644 --- a/man/groff.man +++ b/man/groff.man @@ -2,7 +2,7 @@ .ig groff.man -Last update: 25 June 2002 +Last update: 29 June 2002 This file is part of groff, the GNU roff type-setting system. @@ -83,7 +83,7 @@ FDL in the main directory of the groff source package. . as @s \f[\*[@f2]]\*[@a]\f[]\" . shift . \} -. \*[@m] \*[@s]\f[R] +. \*[@m] "\*[@s]\f[R]" . ft P \" to make \c happy . rm @m . rm @s @@ -521,6 +521,8 @@ request and retrieved by the .esc * escape sequences. . +Strings can have variables. +. .P .B Register variables can store numerical values, numbers with a scale unit, and @@ -564,7 +566,7 @@ The .I italic font is called .B I -is everywhere available, but on text devices, it is displayed as an +and is available everywhere, but on text devices it is displayed as an underlined Roman font. . For the graphical output devices, there exist constant-width pendants @@ -658,7 +660,9 @@ escape sequence. . .TP .character \[dq] -The double quote is used to enclose arguments in requests and macros. +The double quote is used to enclose arguments in requests, macros, and +strings. +. In the .request ds and @@ -711,8 +715,8 @@ Otherwise, it is non-special. \f[CI]space\f[] Space characters are only functional characters. . -They separate the arguments in requests or macros, and the words in -text lines. +They separate the arguments in requests, macros, and strings, and the words +in text lines. . They are subject to groff's horizontal spacing calculations. . @@ -2351,9 +2355,14 @@ The string stored in the string variable with 1-character name The string stored in the string variable with 2-character name .IR st . . -.ESC[] * stringvar +.ESC[] * "stringvar arg1 arg2 .\|.\|." The string stored in the string variable with arbitrary length name -.IR stringvar . +.IR stringvar , +taking +.IR arg1 , +.IR arg2 , +.I .\|.\|.\& +as arguments. . .\" --------- macro arguments --------- . @@ -2365,29 +2374,30 @@ The request can make a macro have more than one name. . .ESC $ x -Macro argument with 1-place number +Macro or string argument with 1-place number .IR x , where .I x is a digit between 1 and 9. . .ESC $( xy -Macro argument with 2-digit number +Macro or string argument with 2-digit number .IR xy . . .ESC[] $ nexp -Macro argument with number +Macro or string argument with number .IR nexp , where .I nexp is a numerical expression evaluating to an integer \[>=]1. . .ESC $* -In a macro, the concatenation of all the arguments separated by spaces. +In a macro or string, the concatenation of all the arguments separated +by spaces. . .ESC $@ -In a macro, the concatenation of all the arguments with each surrounded -by double quotes, and separated by spaces. +In a macro or string, the concatenation of all the arguments with each +surrounded by double quotes, and separated by spaces. . .\" --------- escaped characters --------- . @@ -2881,9 +2891,9 @@ escape sequence. .P Strings share their name space with macros. . -So strings and macros without arguments are roughly equivalent, though -calling a string like a macro and vice-versa is not stably implemented -so far. +So strings and macros without arguments are roughly equivalent; it is +possible to call a string like a macro and vice-versa, but this often +leads to unpredictable results. . The following strings are predefined in groff. . @@ -2942,7 +2952,7 @@ results from request calls. .PD 0 . .REG .$ -Number of arguments in the current macro. +Number of arguments in the current macro or string. . .REG .a Post-line extra line-space most recently utilized using diff --git a/man/groff_diff.man b/man/groff_diff.man index 14b32ec4..0c6df2e6 100644 --- a/man/groff_diff.man +++ b/man/groff_diff.man @@ -3,7 +3,7 @@ .ig groff_diff.man -Last update : 25 June 2002 +Last update : 29 June 2002 This file is part of groff, the GNU roff type-setting system. It is the source of the man-page groff_diff(7). @@ -192,9 +192,14 @@ is a new syntax equal to i.e., to return to the previous font. . .TP -.BI \[rs]*[ xxx ] +.BI \[rs]*[ "xxx arg1 arg2 .\|.\|." ] Interpolate string -.IR xxx . +.IR xxx , +taking +.IR arg1 , +.IR arg2 , +.I .\|.\|.\& +as arguments. . .TP .BI \[rs]n[ xxx ] @@ -673,24 +678,25 @@ request can make a macro have more than one name. . .TP .B \[rs]$* -In a macro, the concatenation of all the arguments separated by spaces. +In a macro or string, the concatenation of all the arguments separated +by spaces. . .TP .B \[rs]$@ -In a macro, the concatenation of all the arguments with each +In a macro or string, the concatenation of all the arguments with each surrounded by double quotes, and separated by spaces. . .TP .BI \[rs]$( nn .TQ .BI \[rs]$[ nnn ] -In a macro, this gives the +In a macro or string, this gives the .IR nn -th or .IR nnn -th argument. . -Macros can have an unlimited number of arguments. +Macros and strings can have an unlimited number of arguments. . .TP .BI \[rs]? anything \[rs]? @@ -2883,8 +2889,8 @@ The same is true for and .BR \[rs]Z . . -When decoding a macro argument that is delimited by double quotes, a -character that appears at a different input level to the starting +When decoding a macro or string argument that is delimited by double +quotes, a character that appears at a different input level to the starting delimiter character will not be recognised as the closing delimiter character. . @@ -2986,7 +2992,7 @@ Only the differences are documented here. The argument to the .B s command is in scaled points (units of -.IR points/ n , +.RI points/ n , where .I n is the argument to the diff --git a/src/roff/troff/input.cc b/src/roff/troff/input.cc index 8fd151ee..a4d28682 100644 --- a/src/roff/troff/input.cc +++ b/src/roff/troff/input.cc @@ -121,6 +121,8 @@ int have_input = 0; // whether \f, \H, \R, \s, or \S has int tcommand_flag = 0; int safer_flag = 1; // safer by default +int have_string_arg = 0; // whether we have \*[foo bar...] + double spread_limit = -3.0 - 1.0; // negative means deactivated double warn_scale; @@ -134,9 +136,11 @@ static void copy_mode_error(const char *, const errarg & = empty_errarg, const errarg & = empty_errarg); -static symbol read_escape_name(int no_empty = 1); -static symbol read_long_escape_name(int no_empty = 1); +enum read_mode { ALLOW_EMPTY, WITH_ARGS, NO_ARGS }; +static symbol read_escape_name(read_mode mode = NO_ARGS); +static symbol read_long_escape_name(read_mode mode = NO_ARGS); static void interpolate_string(symbol); +static void interpolate_string_with_args(symbol); static void interpolate_macro(symbol); static void interpolate_number_format(symbol); static void interpolate_environment_variable(symbol); @@ -690,7 +694,7 @@ void shift() skip_line(); } -static int get_char_for_escape_name() +static int get_char_for_escape_name(int allow_space = 0) { int c = get_copy(0); switch (c) { @@ -704,7 +708,11 @@ static int get_char_for_escape_name() case '\n': if (c == '\n') input_stack::push(make_temp_iterator("\n")); + // fall through case ' ': + if (c == ' ' && allow_space) + break; + // fall through case '\t': case '\001': case '\b': @@ -729,20 +737,25 @@ static symbol read_two_char_escape_name() return symbol(buf); } -static symbol read_long_escape_name(int no_empty) +static symbol read_long_escape_name(read_mode mode) { int start_level = input_stack::get_level(); char abuf[ABUF_SIZE]; char *buf = abuf; int buf_size = ABUF_SIZE; int i = 0; + int c; + int have_char = 0; for (;;) { - int c = get_char_for_escape_name(); + c = get_char_for_escape_name(have_char && mode == WITH_ARGS); if (c == 0) { if (buf != abuf) a_delete buf; return NULL_SYMBOL; } + have_char = 1; + if (mode == WITH_ARGS && c == ' ') + break; if (i + 2 > buf_size) { if (buf == abuf) { buf = new char[ABUF_SIZE*2]; @@ -762,9 +775,11 @@ static symbol read_long_escape_name(int no_empty) buf[i++] = c; } buf[i] = 0; + if (c == ' ') + have_string_arg = 1; if (buf == abuf) { if (i == 0) { - if (no_empty) + if (mode != ALLOW_EMPTY) copy_mode_error("empty escape name"); return EMPTY_SYMBOL; } @@ -777,7 +792,7 @@ static symbol read_long_escape_name(int no_empty) } } -static symbol read_escape_name(int no_empty) +static symbol read_escape_name(read_mode mode) { int c = get_char_for_escape_name(); if (c == 0) @@ -785,7 +800,7 @@ static symbol read_escape_name(int no_empty) if (c == '(') return read_two_char_escape_name(); if (c == '[' && !compatible_flag) - return read_long_escape_name(no_empty); + return read_long_escape_name(mode); char buf[2]; buf[0] = c; buf[1] = '\0'; @@ -861,9 +876,15 @@ static int get_copy(node **nd, int defining) case '*': { (void)input_stack::get(0); - symbol s = read_escape_name(); - if (!(s.is_null() || s.is_empty())) - interpolate_string(s); + symbol s = read_escape_name(WITH_ARGS); + if (!(s.is_null() || s.is_empty())) { + if (have_string_arg) { + have_string_arg = 0; + interpolate_string_with_args(s); + } + else + interpolate_string(s); + } break; } case 'a': @@ -1759,9 +1780,15 @@ void token::next() } case '*': { - symbol nm = read_escape_name(); - if (!(nm.is_null() || nm.is_empty())) - interpolate_string(nm); + symbol nm = read_escape_name(WITH_ARGS); + if (!(nm.is_null() || nm.is_empty())) { + if (have_string_arg) { + have_string_arg = 0; + interpolate_string_with_args(nm); + } + else + interpolate_string(nm); + } break; } case 'a': @@ -1804,7 +1831,7 @@ void token::next() goto handle_escape_char; case 'f': { - symbol s = read_escape_name(0); + symbol s = read_escape_name(ALLOW_EMPTY); if (s.is_null()) break; const char *p; @@ -1821,7 +1848,7 @@ void token::next() } case 'F': { - symbol s = read_escape_name(0); + symbol s = read_escape_name(ALLOW_EMPTY); if (s.is_null()) break; curenv->set_family(s); @@ -1879,13 +1906,13 @@ void token::next() return; } case 'm': - nd = do_glyph_color(read_escape_name(0)); + nd = do_glyph_color(read_escape_name(ALLOW_EMPTY)); if (!nd) break; type = TOKEN_NODE; return; case 'M': - nd = do_fill_color(read_escape_name(0)); + nd = do_fill_color(read_escape_name(ALLOW_EMPTY)); if (!nd) break; type = TOKEN_NODE; @@ -3382,7 +3409,7 @@ static void decode_args(macro_iterator *mi) if (!tok.newline() && !tok.eof()) { node *n; int c = get_copy(&n); - for (;;) { + for (;;) { while (c == ' ') c = get_copy(&n); if (c == '\n' || c == EOF) @@ -3424,6 +3451,56 @@ static void decode_args(macro_iterator *mi) } } +static void decode_string_args(macro_iterator *mi) +{ + node *n; + int c = get_copy(&n); + for (;;) { + while (c == ' ') + c = get_copy(&n); + if (c == '\n' || c == EOF) { + error("missing `]'"); + break; + } + if (c == ']') + break; + macro arg; + int quote_input_level = 0; + int done_tab_warning = 0; + if (c == '\"') { + quote_input_level = input_stack::get_level(); + c = get_copy(&n); + } + while (c != EOF && c != '\n' + && !(c == ']' && quote_input_level == 0) + && !(c == ' ' && quote_input_level == 0)) { + if (quote_input_level > 0 && c == '\"' + && input_stack::get_level() == quote_input_level) { + c = get_copy(&n); + if (c == '"') { + arg.append(c); + c = get_copy(&n); + } + else + break; + } + else { + if (c == 0) + arg.append(n); + else { + if (c == '\t' && quote_input_level == 0 && !done_tab_warning) { + warning(WARN_TAB, "tab character in unquoted string argument"); + done_tab_warning = 1; + } + arg.append(c); + } + c = get_copy(&n); + } + } + mi->add_arg(arg); + } +} + void macro::invoke(symbol nm) { macro_iterator *mi = new macro_iterator(nm, *this); @@ -3696,13 +3773,26 @@ static void interpolate_string(symbol nm) request_or_macro *p = lookup_request(nm); macro *m = p->to_macro(); if (!m) - error("you can only invoke a string using \\*"); + error("you can only invoke a string or macro using \\*"); else { string_iterator *si = new string_iterator(*m, "string", nm); input_stack::push(si); } } +static void interpolate_string_with_args(symbol s) +{ + request_or_macro *p = lookup_request(s); + macro *m = p->to_macro(); + if (!m) + error("you can only invoke a string or macro using \\*"); + else { + macro_iterator *mi = new macro_iterator(s, *m); + decode_string_args(mi); + input_stack::push(mi); + } +} + /* 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 |