summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Forsyth <charles.forsyth@gmail.com>2018-12-23 13:10:38 +0000
committerCharles Forsyth <charles.forsyth@gmail.com>2018-12-23 13:10:38 +0000
commitc3ac38156d7668879ad9f657c762febf341d49f5 (patch)
treec6c68762f8752a1386e239851901b1104dd85c3a
parentf092bcd9be21a77f026a7c3227a920437d35b9e5 (diff)
add -pprefix -t [trace] options to m4
-rw-r--r--appl/cmd/m4.b75
-rw-r--r--dis/m4.disbin12287 -> 12809 bytes
-rw-r--r--man/1/m419
3 files changed, 73 insertions, 21 deletions
diff --git a/appl/cmd/m4.b b/appl/cmd/m4.b
index bc992b4f..a4648d4c 100644
--- a/appl/cmd/m4.b
+++ b/appl/cmd/m4.b
@@ -52,8 +52,11 @@ lquote := '`';
rquote := '\'';
initcom := "#";
endcom := "\n";
+prefix := "";
bout: ref Iobuf;
sh: Sh;
+stderr: ref Sys->FD;
+tracing := 0;
init(nil: ref Draw->Context, args: list of string)
{
@@ -61,9 +64,27 @@ init(nil: ref Draw->Context, args: list of string)
bufio = load Bufio Bufio->PATH;
bout = bufio->fopen(sys->fildes(1), Sys->OWRITE);
+ stderr = sys->fildes(2);
define("inferno", "inferno", 0);
+ arg := load Arg Arg->PATH;
+ arg->setusage("m4 [-t] [-pprefix] [-Dname[=value]] [-Qname[=value]] [-Uname] [file ...]");
+ arg->init(args);
+
+ while((o := arg->opt()) != 0){
+ case o {
+ 'D' or 'Q' or 'U' =>
+ ; # for second pass
+ 'p' =>
+ prefix = arg->earg();
+ 't' =>
+ tracing = 1;
+ * =>
+ arg->usage();
+ }
+ }
+
builtin("changecom", dochangecom);
builtin("changequote", dochangequote);
builtin("copydef", docopydef);
@@ -88,11 +109,9 @@ init(nil: ref Draw->Context, args: list of string)
builtin("undefine", doundefine);
builtin("undivert", doundivert);
- arg := load Arg Arg->PATH;
- arg->setusage("m4 [-Dname[=value]] [-Qname[=value]] [-Uname] [file ...]");
arg->init(args);
- while((o := arg->opt()) != 0){
+ while((o = arg->opt()) != 0){
case o {
'D' =>
argdefine(arg->earg(), 0);
@@ -100,6 +119,10 @@ init(nil: ref Draw->Context, args: list of string)
argdefine(arg->earg(), 1);
'U' =>
undefine(arg->earg());
+ 'p' =>
+ arg->earg();
+ 't' =>
+ ;
* =>
arg->usage();
}
@@ -157,7 +180,8 @@ error(s: string)
ios := hd instack;
where = sys->sprint(" %s:%d:", ios.name, ios.line);
}
- sys->fprint(sys->fildes(2), "m4:%s %s\n", where, s);
+ bout.flush();
+ sys->fprint(stderr, "m4:%s %s\n", where, s);
raise "fail:error";
}
@@ -191,9 +215,12 @@ called(c: int)
curarg = ref Param("");
nesting := 0; # () depth
skipws();
+ mark := instack;
for(;;){
- if((c = getc()) < 0)
+ if((c = getc()) < 0) {
+ instack = mark;
error("EOF in parameters");
+ }
if(isalpha(c))
called(c);
else if(c == lquote)
@@ -228,9 +255,12 @@ called(c: int)
quoted()
{
nesting :=0;
+ mark := instack;
while((c := getc()) != rquote || nesting > 0){
- if(c < 0)
+ if(c < 0) {
+ instack = mark;
error("EOF in string");
+ }
if(c == rquote)
nesting--;
else if(c == lquote)
@@ -276,19 +306,9 @@ isspace(c: int): int
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
-isname(s: string): int
-{
- if(s == nil || !isalpha(s[0]))
- return 0;
- for(i := 1; i < len s; i++)
- if(!(isalpha(s[i]) || s[i]>='0' && s[i]<='9'))
- return 0;
- return 1;
-}
-
isalpha(c: int): int
{
- return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_' || c > 16rA0;
+ return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_' || c > 16rA0 && c != lquote && c != rquote;
}
hash(name: string): int
@@ -301,6 +321,13 @@ hash(name: string): int
builtin(name: string, impl: ref fn(nil: array of string))
{
+ if(prefix != "")
+ name = prefix+name;
+ ibuiltin(name, impl);
+}
+
+ibuiltin(name: string, impl: ref fn(nil: array of string))
+{
h := hash(name);
n := ref Name(name, nil, impl, 0, 0);
names[h] = n :: names[h];
@@ -418,6 +445,12 @@ putc(c: int)
expand(def: ref Name, args: array of string)
{
+ if(tracing){
+ sys->fprint(stderr, "expand %s [%s]", args[0], def.name);
+ for(i := 1; i < len args; i++)
+ sys->fprint(stderr, " %d: [%s]", i, args[i]);
+ sys->fprint(stderr, "\n");
+ }
if(def.impl != nil){
def.impl(args);
return;
@@ -474,7 +507,7 @@ docopydef(args: array of string)
if(n.impl == nil)
define(args[2], n.repl, n.asis);
else
- builtin(args[2], n.impl);
+ ibuiltin(args[2], n.impl);
}else
define(args[2], "", 0);
}
@@ -524,12 +557,12 @@ doundivert(args: array of string)
doifdef(args: array of string)
{
- if(len args < 2)
+ if(len args < 3)
return;
n := lookup(args[1]);
if(n != nil)
pushs(args[2]);
- else if(len args > 2)
+ else if(len args > 3)
pushs(args[3]);
}
@@ -642,7 +675,7 @@ doerrprint(args: array of string)
for(i := 1; i < len args; i++)
s += " "+args[i];
if(s != nil)
- sys->fprint(sys->fildes(2), "m4:%s\n", s);
+ sys->fprint(stderr, "m4:%s\n", s);
}
dolen(args: array of string)
diff --git a/dis/m4.dis b/dis/m4.dis
index f3d48da9..b4f33d37 100644
--- a/dis/m4.dis
+++ b/dis/m4.dis
Binary files differ
diff --git a/man/1/m4 b/man/1/m4
index ef0670a3..08a50990 100644
--- a/man/1/m4
+++ b/man/1/m4
@@ -4,6 +4,12 @@ m4 \- macro processor
.SH SYNOPSIS
.B m4
[
+.BI -p prefix
+]
+[
+.B -t
+]
+[
.BI -D name = value
] [
.BI -Q name = value
@@ -236,7 +242,20 @@ Text may be undiverted into another diversion.
Undiverting discards the diverted text.
.PD
.PP
+The
+.B -p
+option causes
+.I m4
+to add the given prefix character to the names of predefined macros;
+typically the
+.I prefix
+is a Unicode character, to reduce the chance of a clash with macro names in the input text.
+The
+.B -t
+option produces a trace on standard error.
+.PP
.I M4
+otherwise
interprets its command line options after installing the predefined macro set.
The
.B -D