diff options
-rw-r--r-- | ChangeLog | 21 | ||||
-rw-r--r-- | Makefile.in | 49 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | doc/pic.ms | 5 | ||||
-rw-r--r-- | src/preproc/pic/lex.cpp | 81 |
5 files changed, 111 insertions, 48 deletions
@@ -1,3 +1,24 @@ +2006-12-11 Werner LEMBERG <wl@gnu.org> + + Support up to 32 macro arguments in pic (and up to 16 on EBCDIC + hosts). + + * src/preproc/pic/lex.cpp (ARG1): Redefine. Update all users. + (MAX_ARG): New macro. Use it everywhere to replace hard-coded + limit of 9 arguments. + (process_body): Handle argument numbers with more than a single + digit. + (interpolate_macro_with_args): Protect against exceeding number of + arguments. + + * NEWS, src/preproc/pic/pic.man, doc/pic.ms: Document it. + +2006-12-10 Werner LEMBERG <wl@gnu.org> + + * Makefile.in (site.exp, docheck): Commented out. Not working + currently. + (check): Just emit dummy message. + 2006-12-08 Werner LEMBERG <wl@gnu.org> During installation, create soft link from <version> to `current' in diff --git a/Makefile.in b/Makefile.in index 73f569dd..a9ce72c2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -806,32 +806,37 @@ uninstall_dirs: $(libprogramdir) $(libdir) \ $(datadir)/doc/groff $(datadir)/doc $(datadir) 2>/dev/null || : -.PHONY: check docheck -check: site.exp docheck +.PHONY: check +check: + @echo There is no validation suite for this package. -docheck: - if $(SHELL) -c "runtest --version" > /dev/null 2>&1; then \ - runtest; \ - else \ - echo "WARNING: could not find \`runtest'" 1>&2; \ - fi + +#check: site.exp docheck +#.PHONY: docheck + +#docheck: +# if $(SHELL) -c "runtest --version" > /dev/null 2>&1; then \ +# runtest; \ +# else \ +# echo "WARNING: could not find \`runtest'" 1>&2; \ +# fi # This snippet has been taken from the automake package. -site.exp: - @echo "Making a new site.exp file..." - @echo "## these variables are automatically generated by make ##" >site.tmp - @echo "# Do not edit here. If you wish to override these values" >>site.tmp - @echo "# edit the last section" >>site.tmp - @echo "set tool groff" >>site.tmp - @echo "set srcdir $(srcdir)/testsuite" >>site.tmp - @echo "set objdir `pwd`" >> site.tmp - @echo "## All variables above are generated by configure. Do not edit! ##" >> site.tmp - @test ! -f site.exp \ - || sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp - @-rm -f site.bak - @test ! -f site.exp || mv site.exp site.bak - @mv site.tmp site.exp +#site.exp: +# @echo "Making a new site.exp file..." +# @echo "## these variables are automatically generated by make ##" >site.tmp +# @echo "# Do not edit here. If you wish to override these values" >>site.tmp +# @echo "# edit the last section" >>site.tmp +# @echo "set tool groff" >>site.tmp +# @echo "set srcdir $(srcdir)/testsuite" >>site.tmp +# @echo "set objdir `pwd`" >> site.tmp +# @echo "## All variables above are generated by configure. Do not edit! ##" >> site.tmp +# @test ! -f site.exp \ +# || sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp +# @-rm -f site.bak +# @test ! -f site.exp || mv site.exp site.bak +# @mv site.tmp site.exp FORCE: @@ -71,6 +71,9 @@ o int(x) now really behaves as documented: It truncates the non-integer part of x, this is, it rounds towards zero and not towards the next integer less than or equal to x. +o Pic now supports up to 32 macro arguments (and up to 16 on EBCDIC + platforms). + Chem ---- @@ -31,7 +31,7 @@ .\" Eric S. Raymond <esr@thyrsus.com> in August 1995. It has been put .\" under the GPL in March 2006. .\" -.\" $Id: pic.ms,v 1.33 2006/03/21 07:57:57 wl Exp $ +.\" $Id: pic.ms,v 1.34 2006/12/11 16:12:15 wl Exp $ . . .\" Set a proper TeX and LaTeX @@ -1576,7 +1576,8 @@ function that only takes %, %e, %f, and %g format strings. .NH 1 Macros .PP -You can define macros in \fBpic\fP. This is useful for diagrams with +You can define macros in \fBpic\fP, with up to 32 arguments (up to 16 +on EBCDIC platforms). This is useful for diagrams with repetitive parts. In conjunction with the scope rules for block composites, it effectively gives you the ability to write functions. .PP diff --git a/src/preproc/pic/lex.cpp b/src/preproc/pic/lex.cpp index ceca3685..17357ac6 100644 --- a/src/preproc/pic/lex.cpp +++ b/src/preproc/pic/lex.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002, 2003, 2004 +/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) @@ -29,6 +29,16 @@ implement_ptable(char) PTABLE(char) macro_table; +// First character of the range representing $1-$<MAX_ARG>. +// All of them must be invalid input characters. +#ifndef IS_EBCDIC_HOST +#define ARG1 0x80 +#define MAX_ARG 32 +#else +#define ARG1 0x30 +#define MAX_ARG 16 +#endif + class macro_input : public input { char *s; char *p; @@ -44,7 +54,7 @@ class argument_macro_input : public input { char *p; char *ap; int argc; - char *argv[9]; + char *argv[MAX_ARG]; public: argument_macro_input(const char *, int, char **); ~argument_macro_input(); @@ -154,17 +164,29 @@ int macro_input::peek() return (unsigned char)*p; } -// Character representing $1. Must be invalid input character. -#define ARG1 14 - char *process_body(const char *body) { char *s = strsave(body); int j = 0; for (int i = 0; s[i] != '\0'; i++) - if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') { - if (s[i+1] != '0') - s[j++] = ARG1 + s[++i] - '1'; + if (s[i] == '$' && csdigit(s[i + 1])) { + int n = 0; + int start = i; + i++; + while (csdigit(s[i])) + if (n > MAX_ARG) + i++; + else + n = 10 * n + s[i++] - '0'; + if (n > MAX_ARG) { + string arg; + for (int k = start; k < i; k++) + arg += s[k]; + lex_error("invalid macro argument number %1", arg.contents()); + } + else if (n > 0) + s[j++] = ARG1 + n - 1; + i--; } else s[j++] = s[i]; @@ -172,7 +194,6 @@ char *process_body(const char *body) return s; } - argument_macro_input::argument_macro_input(const char *body, int ac, char **av) : ap(0), argc(ac) { @@ -181,7 +202,6 @@ argument_macro_input::argument_macro_input(const char *body, int ac, char **av) p = s = process_body(body); } - argument_macro_input::~argument_macro_input() { for (int i = 0; i < argc; i++) @@ -198,8 +218,9 @@ int argument_macro_input::get() } if (p == 0) return EOF; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; + while ((unsigned char)*p >= ARG1 + && (unsigned char)*p <= ARG1 + MAX_ARG - 1) { + int i = (unsigned char)*p++ - ARG1; if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { ap = argv[i]; return (unsigned char)*ap++; @@ -219,8 +240,9 @@ int argument_macro_input::peek() } if (p == 0) return EOF; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; + while ((unsigned char)*p >= ARG1 + && (unsigned char)*p <= ARG1 + MAX_ARG - 1) { + int i = (unsigned char)*p++ - ARG1; if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { ap = argv[i]; return (unsigned char)*ap; @@ -359,10 +381,11 @@ int token_int; void interpolate_macro_with_args(const char *body) { - char *argv[9]; + char *argv[MAX_ARG]; int argc = 0; + int ignore = 0; int i; - for (i = 0; i < 9; i++) + for (i = 0; i < MAX_ARG; i++) argv[i] = 0; int level = 0; int c; @@ -378,11 +401,19 @@ void interpolate_macro_with_args(const char *body) if (state == NORMAL && level == 0 && (c == ',' || c == ')')) { if (token_buffer.length() > 0) { token_buffer += '\0'; - argv[argc] = strsave(token_buffer.contents()); + if (!ignore) { + if (argc == MAX_ARG) { + lex_warning("only %1 macro arguments supported", MAX_ARG); + ignore = 1; + } + else + argv[argc] = strsave(token_buffer.contents()); + } } // for `foo()', argc = 0 if (argc > 0 || c != ')' || i > 0) - argc++; + if (!ignore) + argc++; break; } token_buffer += char(c); @@ -1441,7 +1472,7 @@ class copy_thru_input : public input { char *until; const char *p; const char *ap; - int argv[9]; + int argv[MAX_ARG]; int argc; string line; int get_line(); @@ -1540,8 +1571,9 @@ int copy_thru_input::get() p = 0; return '\n'; } - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; + while ((unsigned char)*p >= ARG1 + && (unsigned char)*p <= ARG1 + MAX_ARG - 1) { + int i = (unsigned char)*p++ - ARG1; if (i < argc && line[argv[i]] != '\0') { ap = line.contents() + argv[i]; return (unsigned char)*ap++; @@ -1568,8 +1600,9 @@ int copy_thru_input::peek() } if (*p == '\0') return '\n'; - while (*p >= ARG1 && *p <= ARG1 + 8) { - int i = *p++ - ARG1; + while ((unsigned char)*p >= ARG1 + && (unsigned char)*p <= ARG1 + MAX_ARG - 1) { + int i = (unsigned char)*p++ - ARG1; if (i < argc && line[argv[i]] != '\0') { ap = line.contents() + argv[i]; return (unsigned char)*ap; @@ -1593,7 +1626,7 @@ int copy_thru_input::get_line() c = inget(); if (c == EOF || c == '\n') break; - if (argc == 9) { + if (argc == MAX_ARG) { do { c = inget(); } while (c != '\n' && c != EOF); |