mirror of
https://github.com/openbsd/src.git
synced 2025-01-10 06:47:55 -08:00
finally make our m4 SusV3-compliant.
- changecom and changequote have a simple definition (that matches gnu-m4, coincidentally, so we no longer need two distinct modes for these) - off-by-one bug in -s, this finally works. - reorder main parser loop, so that we can use alphabetic constructs in quotes/comments. - rename putback to pushback, this matches comments, and makes more sense. - more uniform (and updated) description of changequote/changecom. - new, systematic regression tests of comments/quotes. - framework to test -s: one perl script to reconstitute `full' files with all line numbers, so that we can verify the output without needing a complete match. okay otto@, fries@
This commit is contained in:
parent
ff117408ee
commit
739ce1244b
@ -1,4 +1,4 @@
|
||||
# $OpenBSD: Makefile,v 1.21 2005/05/17 20:37:11 espie Exp $
|
||||
# $OpenBSD: Makefile,v 1.22 2005/09/06 15:33:21 espie Exp $
|
||||
|
||||
FIBOMAX=25
|
||||
M4=m4
|
||||
@ -10,7 +10,7 @@ REGRESS_TARGETS= test-ff_after_dnl test-m4wrap test-m4wrap2 \
|
||||
test-m4wrap3 test-gm4wrap3 test-fibo \
|
||||
test-patterns trip test-strangequotes test-redef test-quotes \
|
||||
test-weird test-args test-esyscmd test-eval test-gnupatterns \
|
||||
test-gnupatterns2
|
||||
test-gnupatterns2 test-comments test-synch1 test-synch1bis
|
||||
|
||||
test-ff_after_dnl: ff_after_dnl.m4
|
||||
${M4} ff_after_dnl.m4 | diff - ${.CURDIR}/ff_after_dnl.out
|
||||
@ -52,8 +52,9 @@ test-quotes:
|
||||
${M4} ${.CURDIR}/quotes.m4 2>&1| \
|
||||
sed -e 's,\( *\).*/quotes.m4,\1quotes.m4,' | \
|
||||
diff - ${.CURDIR}/quotes.out
|
||||
${M4} -g ${.CURDIR}/quotes.m4 2>&1|diff - ${.CURDIR}/quotes.gnu.out
|
||||
|
||||
test-comments:
|
||||
${M4} ${.CURDIR}/comments.m4 | diff - ${.CURDIR}/comments.out
|
||||
test-strangequotes: strangequotes.m4
|
||||
${M4} strangequotes.m4| diff - ${.CURDIR}/strangequotes.out
|
||||
|
||||
@ -72,6 +73,14 @@ test-esyscmd:
|
||||
test-eval:
|
||||
${M4} ${.CURDIR}/eval.m4 | diff -u - ${.CURDIR}/eval.out
|
||||
|
||||
test-synch1:
|
||||
${M4} -s ${.CURDIR}/synch1.m4|perl ${.CURDIR}/reconstitute|\
|
||||
grep MARK| diff - ${.CURDIR}/synch1.out
|
||||
|
||||
test-synch1bis:
|
||||
${M4} -s <${.CURDIR}/synch1.m4|perl ${.CURDIR}/reconstitute|\
|
||||
grep MARK| diff - ${.CURDIR}/synch1bis.out
|
||||
|
||||
.PHONY: ${REGRESS_TARGETS}
|
||||
|
||||
.include <bsd.regress.mk>
|
||||
|
58
regress/usr.bin/m4/comments.m4
Normal file
58
regress/usr.bin/m4/comments.m4
Normal file
@ -0,0 +1,58 @@
|
||||
dnl $OpenBSD: comments.m4,v 1.1 2005/09/06 15:33:21 espie Exp $
|
||||
dnl checking the way changecom works.
|
||||
1: normal
|
||||
define(`comment', `COMMENT')dnl
|
||||
define(`p', 'XXX')dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
2: `changecom(>>)dnl'
|
||||
changecom(>>)dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
3: `changecom dnl'
|
||||
changecom dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
4: `changecom()dnl'
|
||||
changecom()dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
5: `changecom(,)dnl'
|
||||
changecom(,)dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
6: `changecom(`p',q)dnl'
|
||||
changecom(`p',q)dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
7: `changecom(`p')dnl'
|
||||
changecom(`p')dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
8: `changecom(#)dnl'
|
||||
changecom(#)dnl
|
||||
# this is a comment
|
||||
>> this is a comment
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
47
regress/usr.bin/m4/comments.out
Normal file
47
regress/usr.bin/m4/comments.out
Normal file
@ -0,0 +1,47 @@
|
||||
1: normal
|
||||
# this is a comment
|
||||
>> this is a COMMENT
|
||||
'XXX' this is a COMMENT
|
||||
'XXX' this is a COMMENT q COMMENT too
|
||||
|
||||
2: changecom(>>)dnl
|
||||
# this is a COMMENT
|
||||
>> this is a comment
|
||||
'XXX' this is a COMMENT
|
||||
'XXX' this is a COMMENT q COMMENT too
|
||||
|
||||
3: changecom dnl
|
||||
# this is a COMMENT
|
||||
>> this is a COMMENT
|
||||
'XXX' this is a COMMENT
|
||||
'XXX' this is a COMMENT q COMMENT too
|
||||
|
||||
4: changecom()dnl
|
||||
# this is a COMMENT
|
||||
>> this is a COMMENT
|
||||
'XXX' this is a COMMENT
|
||||
'XXX' this is a COMMENT q COMMENT too
|
||||
|
||||
5: changecom(,)dnl
|
||||
# this is a COMMENT
|
||||
>> this is a COMMENT
|
||||
'XXX' this is a COMMENT
|
||||
'XXX' this is a COMMENT q COMMENT too
|
||||
|
||||
6: changecom(`p',q)dnl
|
||||
# this is a COMMENT
|
||||
>> this is a COMMENT
|
||||
p this is a comment
|
||||
p this is a comment q COMMENT too
|
||||
|
||||
7: changecom(`p')dnl
|
||||
# this is a COMMENT
|
||||
>> this is a COMMENT
|
||||
p this is a comment
|
||||
p this is a comment q comment too
|
||||
|
||||
8: changecom(#)dnl
|
||||
# this is a comment
|
||||
>> this is a COMMENT
|
||||
'XXX' this is a COMMENT
|
||||
'XXX' this is a COMMENT q COMMENT too
|
@ -1,21 +1,57 @@
|
||||
dnl $OpenBSD: quotes.m4,v 1.1 2001/09/29 15:49:18 espie Exp $
|
||||
dnl $OpenBSD: quotes.m4,v 1.2 2005/09/06 15:33:21 espie Exp $
|
||||
dnl Checking the way changequote() is supposed to work
|
||||
dnl in both normal and gnu emulation mode
|
||||
define(`string',`STRING')dnl
|
||||
1: normal
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
||||
2: kill quotes
|
||||
changequote()dnl
|
||||
`No quotes left'
|
||||
changequote([,])dnl
|
||||
[Quotes]changequote
|
||||
`No quotes left'
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
||||
3: normal changed quote
|
||||
changequote([,])dnl
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
||||
4: empty quotes, kill them too
|
||||
changequote(,)dnl
|
||||
`No quotes left'
|
||||
changequote([,])dnl
|
||||
dnl same thing with comments, so first:
|
||||
define([comment], [COMMENT])dnl
|
||||
# this is a comment
|
||||
changecom(>>)dnl
|
||||
# this is a comment
|
||||
changecom
|
||||
# this is a comment
|
||||
changecom(,)dnl
|
||||
# this is a comment
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
||||
5: start quote only
|
||||
changequote(`)dnl
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
||||
6: normal quotes are back
|
||||
changequote
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
||||
7: start quote+empty end quote
|
||||
changequote([,)dnl
|
||||
`quoted string'
|
||||
[quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
@ -1,9 +1,49 @@
|
||||
No quotes left
|
||||
Quotes
|
||||
No quotes left
|
||||
No quotes left'
|
||||
changequote([,)# this is a comment
|
||||
# this is a comment
|
||||
m4: unclosed quote:
|
||||
quotes.m4 at line 54
|
||||
1: normal
|
||||
quoted string
|
||||
[quoted STRING]
|
||||
normal STRING
|
||||
half quoted string
|
||||
going up to that string
|
||||
|
||||
# this is a comment
|
||||
# this is a comment
|
||||
2: kill quotes
|
||||
`quoted STRING'
|
||||
[quoted STRING]
|
||||
normal STRING
|
||||
`half quoted STRING
|
||||
going up to that STRING'
|
||||
|
||||
3: normal changed quote
|
||||
`quoted STRING'
|
||||
quoted string
|
||||
normal STRING
|
||||
`half quoted STRING
|
||||
going up to that STRING'
|
||||
|
||||
4: empty quotes, kill them too
|
||||
`quoted STRING'
|
||||
[quoted STRING]
|
||||
normal STRING
|
||||
`half quoted STRING
|
||||
going up to that STRING'
|
||||
|
||||
5: start quote only
|
||||
quoted string'[quoted STRING]
|
||||
normal STRING
|
||||
half quoted stringgoing up to that STRING'
|
||||
|
||||
6: normal quotes are back
|
||||
|
||||
quoted string
|
||||
[quoted STRING]
|
||||
normal STRING
|
||||
half quoted string
|
||||
going up to that string
|
||||
|
||||
7: start quote+empty end quote
|
||||
`quoted STRING'
|
||||
quoted string]
|
||||
normal string
|
||||
`half quoted string
|
||||
going up to that string'
|
||||
|
24
regress/usr.bin/m4/reconstitute
Normal file
24
regress/usr.bin/m4/reconstitute
Normal file
@ -0,0 +1,24 @@
|
||||
#! /usr/bin/perl
|
||||
# $OpenBSD: reconstitute,v 1.1 2005/09/06 15:33:21 espie Exp $
|
||||
|
||||
# Written by Marc Espie, 2005
|
||||
# Public domain
|
||||
|
||||
# This simple perl script puts back line numbers everywhere.
|
||||
# This is suitable for testing synchronization, as we don't really
|
||||
# care how many synchronization marks we emit, as long as the line
|
||||
# numbers match
|
||||
|
||||
use File::Basename;
|
||||
|
||||
my ($lineno, $file) = (-1, "<unknown>");
|
||||
|
||||
while (<>) {
|
||||
if (m/^#line\s+(\d+)\s+\"(.*)\"/) {
|
||||
($lineno, $file) = ($1, $2);
|
||||
$file=basename($file);
|
||||
} else {
|
||||
print "$file:$lineno:$_";
|
||||
$lineno++;
|
||||
}
|
||||
}
|
13
regress/usr.bin/m4/synch1.m4
Normal file
13
regress/usr.bin/m4/synch1.m4
Normal file
@ -0,0 +1,13 @@
|
||||
This is a test for multi MARK1
|
||||
line synchronization stuff MARK2
|
||||
# Let's include comments to see MARK3
|
||||
dnl
|
||||
dnl
|
||||
`quoted string' MARK4
|
||||
define(`A',`big string
|
||||
with a newline embedded')dnl
|
||||
Return to normal MARK5
|
||||
Let's try A
|
||||
And let's see where we are now. MARK6
|
||||
Okay, some more input.
|
||||
MARK7
|
7
regress/usr.bin/m4/synch1.out
Normal file
7
regress/usr.bin/m4/synch1.out
Normal file
@ -0,0 +1,7 @@
|
||||
synch1.m4:1:This is a test for multi MARK1
|
||||
synch1.m4:2:line synchronization stuff MARK2
|
||||
synch1.m4:3:# Let's include comments to see MARK3
|
||||
synch1.m4:4:quoted string MARK4
|
||||
synch1.m4:7:Return to normal MARK5
|
||||
synch1.m4:11:And let's see where we are now. MARK6
|
||||
synch1.m4:13:MARK7
|
7
regress/usr.bin/m4/synch1bis.out
Normal file
7
regress/usr.bin/m4/synch1bis.out
Normal file
@ -0,0 +1,7 @@
|
||||
stdin:1:This is a test for multi MARK1
|
||||
stdin:2:line synchronization stuff MARK2
|
||||
stdin:3:# Let's include comments to see MARK3
|
||||
stdin:4:quoted string MARK4
|
||||
stdin:7:Return to normal MARK5
|
||||
stdin:11:And let's see where we are now. MARK6
|
||||
stdin:13:MARK7
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: eval.c,v 1.57 2005/08/06 16:22:26 espie Exp $ */
|
||||
/* $OpenBSD: eval.c,v 1.58 2005/09/06 15:33:21 espie Exp $ */
|
||||
/* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */
|
||||
|
||||
/*
|
||||
@ -61,9 +61,7 @@ static void dotrace(const char *[], int, int);
|
||||
static void doifelse(const char *[], int);
|
||||
static int doincl(const char *);
|
||||
static int dopaste(const char *);
|
||||
static void gnu_dochq(const char *[], int);
|
||||
static void dochq(const char *[], int);
|
||||
static void gnu_dochc(const char *[], int);
|
||||
static void dochc(const char *[], int);
|
||||
static void dom4wrap(const char *);
|
||||
static void dodiv(int);
|
||||
@ -136,6 +134,9 @@ expand_builtin(const char *argv[], int argc, int td)
|
||||
* if argc == 3 and argv[2] is null, then we
|
||||
* have macro-or-builtin() type call. We adjust
|
||||
* argc to avoid further checking..
|
||||
*/
|
||||
/* we keep the initial value for those built-ins that differentiate
|
||||
* between builtin() and builtin.
|
||||
*/
|
||||
ac = argc;
|
||||
|
||||
@ -286,17 +287,11 @@ expand_builtin(const char *argv[], int argc, int td)
|
||||
break;
|
||||
#endif
|
||||
case CHNQTYPE:
|
||||
if (mimic_gnu)
|
||||
gnu_dochq(argv, ac);
|
||||
else
|
||||
dochq(argv, argc);
|
||||
dochq(argv, ac);
|
||||
break;
|
||||
|
||||
case CHNCTYPE:
|
||||
if (mimic_gnu)
|
||||
gnu_dochc(argv, ac);
|
||||
else
|
||||
dochc(argv, argc);
|
||||
dochc(argv, argc);
|
||||
break;
|
||||
|
||||
case SUBSTYPE:
|
||||
@ -319,7 +314,7 @@ expand_builtin(const char *argv[], int argc, int td)
|
||||
pbstr(rquote);
|
||||
pbstr(argv[n]);
|
||||
pbstr(lquote);
|
||||
putback(COMMA);
|
||||
pushback(COMMA);
|
||||
}
|
||||
pbstr(rquote);
|
||||
pbstr(argv[3]);
|
||||
@ -518,7 +513,7 @@ expand_macro(const char *argv[], int argc)
|
||||
p--; /* last character of defn */
|
||||
while (p > t) {
|
||||
if (*(p - 1) != ARGFLAG)
|
||||
PUTBACK(*p);
|
||||
PUSHBACK(*p);
|
||||
else {
|
||||
switch (*p) {
|
||||
|
||||
@ -542,7 +537,7 @@ expand_macro(const char *argv[], int argc)
|
||||
if (argc > 2) {
|
||||
for (n = argc - 1; n > 2; n--) {
|
||||
pbstr(argv[n]);
|
||||
putback(COMMA);
|
||||
pushback(COMMA);
|
||||
}
|
||||
pbstr(argv[2]);
|
||||
}
|
||||
@ -553,7 +548,7 @@ expand_macro(const char *argv[], int argc)
|
||||
pbstr(rquote);
|
||||
pbstr(argv[n]);
|
||||
pbstr(lquote);
|
||||
putback(COMMA);
|
||||
pushback(COMMA);
|
||||
}
|
||||
pbstr(rquote);
|
||||
pbstr(argv[2]);
|
||||
@ -561,8 +556,8 @@ expand_macro(const char *argv[], int argc)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PUTBACK(*p);
|
||||
PUTBACK('$');
|
||||
PUSHBACK(*p);
|
||||
PUSHBACK('$');
|
||||
break;
|
||||
}
|
||||
p--;
|
||||
@ -570,7 +565,7 @@ expand_macro(const char *argv[], int argc)
|
||||
p--;
|
||||
}
|
||||
if (p == t) /* do last character */
|
||||
PUTBACK(*p);
|
||||
PUSHBACK(*p);
|
||||
}
|
||||
|
||||
|
||||
@ -736,85 +731,44 @@ dopaste(const char *pfile)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gnu_dochq(const char *argv[], int ac)
|
||||
{
|
||||
/* In gnu-m4 mode, the only way to restore quotes is to have no
|
||||
* arguments at all. */
|
||||
if (ac == 2) {
|
||||
lquote[0] = LQUOTE, lquote[1] = EOS;
|
||||
rquote[0] = RQUOTE, rquote[1] = EOS;
|
||||
} else {
|
||||
strlcpy(lquote, argv[2], sizeof(lquote));
|
||||
if(ac > 3)
|
||||
strlcpy(rquote, argv[3], sizeof(rquote));
|
||||
else
|
||||
rquote[0] = EOS;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* dochq - change quote characters
|
||||
*/
|
||||
static void
|
||||
dochq(const char *argv[], int argc)
|
||||
dochq(const char *argv[], int ac)
|
||||
{
|
||||
if (argc > 2) {
|
||||
if (*argv[2])
|
||||
strlcpy(lquote, argv[2], sizeof(lquote));
|
||||
else {
|
||||
lquote[0] = LQUOTE;
|
||||
lquote[1] = EOS;
|
||||
}
|
||||
if (argc > 3) {
|
||||
if (*argv[3])
|
||||
strlcpy(rquote, argv[3], sizeof(rquote));
|
||||
} else
|
||||
strlcpy(rquote, lquote, sizeof(rquote));
|
||||
if (ac == 2) {
|
||||
lquote[0] = LQUOTE; lquote[1] = EOS;
|
||||
rquote[0] = RQUOTE; rquote[1] = EOS;
|
||||
} else {
|
||||
lquote[0] = LQUOTE, lquote[1] = EOS;
|
||||
rquote[0] = RQUOTE, rquote[1] = EOS;
|
||||
strlcpy(lquote, argv[2], sizeof(lquote));
|
||||
if (ac > 3) {
|
||||
strlcpy(rquote, argv[3], sizeof(rquote));
|
||||
} else {
|
||||
rquote[0] = ECOMMT; rquote[1] = EOS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gnu_dochc(const char *argv[], int ac)
|
||||
{
|
||||
/* In gnu-m4 mode, no arguments mean no comment
|
||||
* arguments at all. */
|
||||
if (ac == 2) {
|
||||
scommt[0] = EOS;
|
||||
ecommt[0] = EOS;
|
||||
} else {
|
||||
if (*argv[2])
|
||||
strlcpy(scommt, argv[2], sizeof(scommt));
|
||||
else
|
||||
scommt[0] = SCOMMT, scommt[1] = EOS;
|
||||
if(ac > 3 && *argv[3])
|
||||
strlcpy(ecommt, argv[3], sizeof(ecommt));
|
||||
else
|
||||
ecommt[0] = ECOMMT, ecommt[1] = EOS;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* dochc - change comment characters
|
||||
*/
|
||||
static void
|
||||
dochc(const char *argv[], int argc)
|
||||
{
|
||||
if (argc > 2) {
|
||||
if (*argv[2])
|
||||
strlcpy(scommt, argv[2], sizeof(scommt));
|
||||
if (argc > 3) {
|
||||
if (*argv[3])
|
||||
strlcpy(ecommt, argv[3], sizeof(ecommt));
|
||||
/* XXX Note that there is no difference between no argument and a single
|
||||
* empty argument.
|
||||
*/
|
||||
if (argc == 2) {
|
||||
scommt[0] = EOS;
|
||||
ecommt[0] = EOS;
|
||||
} else {
|
||||
strlcpy(scommt, argv[2], sizeof(scommt));
|
||||
if (argc == 3) {
|
||||
ecommt[0] = ECOMMT; ecommt[1] = EOS;
|
||||
} else {
|
||||
strlcpy(ecommt, argv[3], sizeof(ecommt));
|
||||
}
|
||||
else
|
||||
ecommt[0] = ECOMMT, ecommt[1] = EOS;
|
||||
}
|
||||
else {
|
||||
scommt[0] = SCOMMT, scommt[1] = EOS;
|
||||
ecommt[0] = ECOMMT, ecommt[1] = EOS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -918,7 +872,7 @@ dosub(const char *argv[], int argc)
|
||||
#endif
|
||||
if (fc >= ap && fc < ap + strlen(ap))
|
||||
for (k = fc + nc - 1; k >= fc; k--)
|
||||
putback(*k);
|
||||
pushback(*k);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: extern.h,v 1.41 2005/05/29 18:44:36 espie Exp $ */
|
||||
/* $OpenBSD: extern.h,v 1.42 2005/09/06 15:33:21 espie Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $ */
|
||||
|
||||
/*-
|
||||
@ -100,7 +100,7 @@ extern void pbnum(int);
|
||||
extern void pbnumbase(int, int, int);
|
||||
extern void pbunsigned(unsigned long);
|
||||
extern void pbstr(const char *);
|
||||
extern void putback(int);
|
||||
extern void pushback(int);
|
||||
extern void *xalloc(size_t, const char *fmt, ...);
|
||||
extern void *xrealloc(void *, size_t, const char *fmt, ...);
|
||||
extern char *xstrdup(const char *);
|
||||
@ -113,8 +113,8 @@ extern int obtain_char(struct input_file *);
|
||||
extern void set_input(struct input_file *, FILE *, const char *);
|
||||
extern void release_input(struct input_file *);
|
||||
|
||||
/* speeded-up versions of chrsave/putback */
|
||||
#define PUTBACK(c) \
|
||||
/* speeded-up versions of chrsave/pushback */
|
||||
#define PUSHBACK(c) \
|
||||
do { \
|
||||
if (bp >= endpbb) \
|
||||
enlarge_bufspace(); \
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" @(#) $OpenBSD: m4.1,v 1.38 2005/03/02 10:12:15 espie Exp $
|
||||
.\" @(#) $OpenBSD: m4.1,v 1.39 2005/09/06 15:33:21 espie Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
@ -155,17 +155,29 @@ Calls a built-in by its
|
||||
.Fa name ,
|
||||
overriding possible redefinitions.
|
||||
.It Fn changecom startcomment endcomment
|
||||
Change the start and end comment sequences.
|
||||
The default is the pound sign
|
||||
.Pq Sq #
|
||||
Changes the start comment and end comment sequences.
|
||||
Comment sequences may be up to five characters long.
|
||||
The default values are the pound sign
|
||||
and the newline character.
|
||||
With no arguments comments are turned off.
|
||||
The maximum length for a comment marker is five characters.
|
||||
.Bd -literal -offset indent
|
||||
# This is a comment
|
||||
.Ed
|
||||
.Pp
|
||||
With no arguments, comments are turned off.
|
||||
With one single argument, the end comment sequence is set
|
||||
to the newline character.
|
||||
.It Fn changequote beginquote endquote
|
||||
Defines the quote symbols to be the first and second arguments.
|
||||
The symbols may be up to five characters long.
|
||||
If no arguments are
|
||||
given it restores the default open and close single quotes.
|
||||
Defines the open quote and close quote sequences.
|
||||
Quote sequences may be up to five characters long.
|
||||
The default values are the backquote character and the quote
|
||||
character.
|
||||
.Bd -literal -offset indent
|
||||
`Here is a quoted string'
|
||||
.Ed
|
||||
.Pp
|
||||
With no arguments, the default quotes are restored.
|
||||
With one single argument, the close quote sequence is set
|
||||
to the newline character.
|
||||
.It Fn decr arg
|
||||
Decrements the argument
|
||||
.Fa arg
|
||||
@ -386,18 +398,10 @@ Returns the current file's name.
|
||||
.El
|
||||
.Sh STANDARDS
|
||||
.Nm
|
||||
follows the Single Unix 2 specification, along with a few extensions taken
|
||||
follows the Single Unix 3 specification, along with a few extensions taken
|
||||
from
|
||||
.Nm gnu-m4 .
|
||||
.Pp
|
||||
The
|
||||
.Fl s
|
||||
option
|
||||
.Po
|
||||
.Xr cpp 1 's
|
||||
#line directives
|
||||
.Pc
|
||||
is currently not supported.
|
||||
Flags
|
||||
.Fl I ,
|
||||
.Fl d ,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: main.c,v 1.67 2005/08/06 16:22:26 espie Exp $ */
|
||||
/* $OpenBSD: main.c,v 1.68 2005/09/06 15:33:21 espie Exp $ */
|
||||
/* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */
|
||||
|
||||
/*-
|
||||
@ -296,9 +296,9 @@ do_look_ahead(int t, const char *token)
|
||||
for (i = 1; *++token; i++) {
|
||||
t = gpbc();
|
||||
if (t == EOF || (unsigned char)t != (unsigned char)*token) {
|
||||
putback(t);
|
||||
pushback(t);
|
||||
while (--i)
|
||||
putback(*--token);
|
||||
pushback(*--token);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -322,10 +322,57 @@ macro(void)
|
||||
|
||||
cycle {
|
||||
t = gpbc();
|
||||
if (t == '_' || isalpha(t)) {
|
||||
|
||||
if (LOOK_AHEAD(t,lquote)) { /* strip quotes */
|
||||
nlpar = 0;
|
||||
record(quotes, nlpar++);
|
||||
/*
|
||||
* Opening quote: scan forward until matching
|
||||
* closing quote has been found.
|
||||
*/
|
||||
do {
|
||||
|
||||
l = gpbc();
|
||||
if (LOOK_AHEAD(l,rquote)) {
|
||||
if (--nlpar > 0)
|
||||
outputstr(rquote);
|
||||
} else if (LOOK_AHEAD(l,lquote)) {
|
||||
record(quotes, nlpar++);
|
||||
outputstr(lquote);
|
||||
} else if (l == EOF) {
|
||||
if (nlpar == 1)
|
||||
warnx("unclosed quote:");
|
||||
else
|
||||
warnx("%d unclosed quotes:", nlpar);
|
||||
dump_stack(quotes, nlpar);
|
||||
exit(1);
|
||||
} else {
|
||||
if (nlpar > 0) {
|
||||
if (sp < 0)
|
||||
reallyputchar(l);
|
||||
else
|
||||
CHRSAVE(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (nlpar != 0);
|
||||
} else if (sp < 0 && LOOK_AHEAD(t, scommt)) {
|
||||
reallyoutputstr(scommt);
|
||||
|
||||
for(;;) {
|
||||
t = gpbc();
|
||||
if (LOOK_AHEAD(t, ecommt)) {
|
||||
reallyoutputstr(ecommt);
|
||||
break;
|
||||
}
|
||||
if (t == EOF)
|
||||
break;
|
||||
reallyputchar(t);
|
||||
}
|
||||
} else if (t == '_' || isalpha(t)) {
|
||||
p = inspect(t, token);
|
||||
if (p != NULL)
|
||||
putback(l = gpbc());
|
||||
pushback(l = gpbc());
|
||||
if (p == NULL || (l != LPAREN &&
|
||||
(macro_getdef(p)->type & NEEDARGS) != 0))
|
||||
outputstr(token);
|
||||
@ -371,62 +418,7 @@ macro(void)
|
||||
emit_synchline();
|
||||
bufbase = bbase[ilevel];
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* non-alpha token possibly seen..
|
||||
* [the order of else if .. stmts is important.]
|
||||
*/
|
||||
else if (LOOK_AHEAD(t,lquote)) { /* strip quotes */
|
||||
nlpar = 0;
|
||||
record(quotes, nlpar++);
|
||||
/*
|
||||
* Opening quote: scan forward until matching
|
||||
* closing quote has been found.
|
||||
*/
|
||||
do {
|
||||
|
||||
l = gpbc();
|
||||
if (LOOK_AHEAD(l,rquote)) {
|
||||
if (--nlpar > 0)
|
||||
outputstr(rquote);
|
||||
} else if (LOOK_AHEAD(l,lquote)) {
|
||||
record(quotes, nlpar++);
|
||||
outputstr(lquote);
|
||||
} else if (l == EOF) {
|
||||
if (nlpar == 1)
|
||||
warnx("unclosed quote:");
|
||||
else
|
||||
warnx("%d unclosed quotes:", nlpar);
|
||||
dump_stack(quotes, nlpar);
|
||||
exit(1);
|
||||
} else {
|
||||
if (nlpar > 0) {
|
||||
if (sp < 0)
|
||||
reallyputchar(l);
|
||||
else
|
||||
CHRSAVE(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (nlpar != 0);
|
||||
}
|
||||
|
||||
else if (sp < 0 && LOOK_AHEAD(t, scommt)) {
|
||||
reallyoutputstr(scommt);
|
||||
|
||||
for(;;) {
|
||||
t = gpbc();
|
||||
if (LOOK_AHEAD(t, ecommt)) {
|
||||
reallyoutputstr(ecommt);
|
||||
break;
|
||||
}
|
||||
if (t == EOF)
|
||||
break;
|
||||
reallyputchar(t);
|
||||
}
|
||||
}
|
||||
|
||||
else if (sp < 0) { /* not in a macro at all */
|
||||
} else if (sp < 0) { /* not in a macro at all */
|
||||
reallyputchar(t); /* output directly.. */
|
||||
}
|
||||
|
||||
@ -437,7 +429,7 @@ macro(void)
|
||||
chrsave(t);
|
||||
while (isspace(l = gpbc()))
|
||||
; /* skip blank, tab, nl.. */
|
||||
putback(l);
|
||||
pushback(l);
|
||||
record(paren, PARLEV++);
|
||||
break;
|
||||
|
||||
@ -464,7 +456,7 @@ macro(void)
|
||||
chrsave(EOS); /* new argument */
|
||||
while (isspace(l = gpbc()))
|
||||
;
|
||||
putback(l);
|
||||
pushback(l);
|
||||
pushs(ep);
|
||||
} else
|
||||
chrsave(t);
|
||||
@ -550,7 +542,7 @@ inspect(int c, char *tp)
|
||||
while ((isalnum(c = gpbc()) || c == '_') && tp < etp)
|
||||
*tp++ = c;
|
||||
if (c != EOF)
|
||||
PUTBACK(c);
|
||||
PUSHBACK(c);
|
||||
*tp = EOS;
|
||||
/* token is too long, it won't match anything, but it can still
|
||||
* be output. */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: misc.c,v 1.32 2005/08/06 16:22:26 espie Exp $ */
|
||||
/* $OpenBSD: misc.c,v 1.33 2005/09/06 15:33:21 espie Exp $ */
|
||||
/* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */
|
||||
|
||||
/*
|
||||
@ -76,10 +76,10 @@ indx(const char *s1, const char *s2)
|
||||
return (t - s1);
|
||||
}
|
||||
/*
|
||||
* putback - push character back onto input
|
||||
* pushback - push character back onto input
|
||||
*/
|
||||
void
|
||||
putback(int c)
|
||||
pushback(int c)
|
||||
{
|
||||
if (c == EOF)
|
||||
return;
|
||||
@ -90,7 +90,7 @@ putback(int c)
|
||||
|
||||
/*
|
||||
* pbstr - push string back onto input
|
||||
* putback is replicated to improve
|
||||
* pushback is replicated to improve
|
||||
* performance.
|
||||
*/
|
||||
void
|
||||
@ -129,7 +129,7 @@ pbnumbase(int n, int base, int d)
|
||||
|
||||
num = (n < 0) ? -n : n;
|
||||
do {
|
||||
putback(digits[num % base]);
|
||||
pushback(digits[num % base]);
|
||||
printed++;
|
||||
}
|
||||
while ((num /= base) > 0);
|
||||
@ -137,10 +137,10 @@ pbnumbase(int n, int base, int d)
|
||||
if (n < 0)
|
||||
printed++;
|
||||
while (printed++ < d)
|
||||
putback('0');
|
||||
pushback('0');
|
||||
|
||||
if (n < 0)
|
||||
putback('-');
|
||||
pushback('-');
|
||||
}
|
||||
|
||||
/*
|
||||
@ -150,7 +150,7 @@ void
|
||||
pbunsigned(unsigned long n)
|
||||
{
|
||||
do {
|
||||
putback(n % 10 + '0');
|
||||
pushback(n % 10 + '0');
|
||||
}
|
||||
while ((n /= 10) > 0);
|
||||
}
|
||||
@ -332,10 +332,11 @@ obtain_char(struct input_file *f)
|
||||
{
|
||||
if (f->c == EOF)
|
||||
return EOF;
|
||||
else if (f->c == '\n')
|
||||
f->lineno++;
|
||||
|
||||
f->c = fgetc(f->file);
|
||||
if (f->c == '\n')
|
||||
f->lineno++;
|
||||
|
||||
return f->c;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user