summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog21
-rw-r--r--Makefile.in49
-rw-r--r--NEWS3
-rw-r--r--doc/pic.ms5
-rw-r--r--src/preproc/pic/lex.cpp81
5 files changed, 111 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index 6cff2d44..87ada3b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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:
diff --git a/NEWS b/NEWS
index f872fa43..7745d533 100644
--- a/NEWS
+++ b/NEWS
@@ -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
----
diff --git a/doc/pic.ms b/doc/pic.ms
index 27fcd1de..91654d68 100644
--- a/doc/pic.ms
+++ b/doc/pic.ms
@@ -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);