argument parsing should only skip spaces outside of parenthesis.
authorespie <espie@openbsd.org>
Sat, 16 Aug 2008 12:21:46 +0000 (12:21 +0000)
committerespie <espie@openbsd.org>
Sat, 16 Aug 2008 12:21:46 +0000 (12:21 +0000)
Inside matching parenthesis, keep spaces as is (use chrsave instead of
pbstr, since there's no way it can be a further macro expansion).
Fixes a long-standing issue with autoconf (   --option -> --option),
matches other m4 than gnum4

okay millert@, fries@

usr.bin/m4/eval.c
usr.bin/m4/extern.h
usr.bin/m4/gnum4.c
usr.bin/m4/m4.1
usr.bin/m4/main.c
usr.bin/m4/misc.c
usr.bin/m4/parser.y
usr.bin/m4/tokenizer.l

index bd9cb89..e67a71c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: eval.c,v 1.63 2006/03/24 08:03:44 espie Exp $ */
+/*     $OpenBSD: eval.c,v 1.64 2008/08/16 12:21:46 espie Exp $ */
 /*     $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $      */
 
 /*
@@ -139,7 +139,7 @@ expand_builtin(const char *argv[], int argc, int td)
   */
        ac = argc;
 
-       if (argc == 3 && !*(argv[2]))
+       if (argc == 3 && !*(argv[2]) && !mimic_gnu)
                argc--;
 
        switch (td & TYPEMASK) {
@@ -576,9 +576,10 @@ expand_macro(const char *argv[], int argc)
 void
 dodefine(const char *name, const char *defn)
 {
-       if (!*name)
+       if (!*name && !mimic_gnu)
                m4errx(1, "null definition.");
-       macro_define(name, defn);
+       else 
+               macro_define(name, defn);
 }
 
 /*
@@ -612,9 +613,10 @@ dodefn(const char *name)
 static void
 dopushdef(const char *name, const char *defn)
 {
-       if (!*name)
+       if (!*name && !mimic_gnu)
                m4errx(1, "null definition.");
-       macro_pushdef(name, defn);
+       else
+               macro_pushdef(name, defn);
 }
 
 /*
index 01df741..16aaf2b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.45 2006/03/20 20:27:45 espie Exp $       */
+/*     $OpenBSD: extern.h,v 1.46 2008/08/16 12:21:46 espie Exp $       */
 /*     $NetBSD: extern.h,v 1.3 1996/01/13 23:25:24 pk Exp $    */
 
 /*-
@@ -109,7 +109,7 @@ extern void usage(void);
 extern void    resizedivs(int);
 extern size_t  buffer_mark(void);
 extern void    dump_buffer(FILE *, size_t);
-extern void    m4errx(int, const char *, ...);
+extern void    __dead m4errx(int, const char *, ...);
 
 extern int     obtain_char(struct input_file *);
 extern void    set_input(struct input_file *, FILE *, const char *);
@@ -133,7 +133,7 @@ extern void release_input(struct input_file *);
 /* and corresponding exposure for local symbols */
 extern void enlarge_bufspace(void);
 extern void enlarge_strspace(void);
-extern char *endpbb;
+extern unsigned char *endpbb;
 extern char *endest;
 
 /* trace.c */
@@ -156,10 +156,10 @@ extern int fp;                    /* m4 call frame pointer */
 extern int ilevel;             /* input file stack pointer */
 extern int oindex;             /* diversion index. */
 extern int sp;                 /* current m4 stack pointer */
-extern char *bp;               /* first available character */
-extern char *buf;              /* push-back buffer */
-extern char *bufbase;          /* buffer base for this ilevel */
-extern char *bbase[];          /* buffer base per ilevel */
+extern unsigned char *bp;      /* first available character */
+extern unsigned char *buf;     /* push-back buffer */
+extern unsigned char *bufbase; /* buffer base for this ilevel */
+extern unsigned char *bbase[]; /* buffer base per ilevel */
 extern char ecommt[MAXCCHARS+1];/* end character for comment */
 extern char *ep;               /* first free char in strspace */
 extern char lquote[MAXCCHARS+1];/* left quote character (`) */
index 2720c85..f9ee4ed 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: gnum4.c,v 1.36 2006/03/24 08:03:44 espie Exp $ */
+/* $OpenBSD: gnum4.c,v 1.37 2008/08/16 12:21:46 espie Exp $ */
 
 /*
  * Copyright (c) 1999 Marc Espie
@@ -508,43 +508,85 @@ doformat(const char *argv[], int argc)
 {
        const char *format = argv[2];
        int pos = 3;
+       int left_padded;
+       long width;
+       size_t l;
+       const char *thisarg;
+       char temp[2];
+       long extra;
 
        while (*format != 0) {
                if (*format != '%') {
                        addchar(*format++);
+                       continue;
+               }
+
+               format++;
+               if (*format == '%') {
+                       addchar(*format++);
+                       continue;
+               }
+               if (*format == 0) {
+                       addchar('%');
+                       break;
+               }
+
+               if (*format == '*') {
+                       format++;
+                       if (pos >= argc)
+                               m4errx(1, 
+                                   "Format with too many format specifiers.");
+                       width = strtol(argv[pos++], NULL, 10);
+               } else {
+                       width = strtol(format, (char **)&format, 10);
+               }
+               if (width < 0) {
+                       left_padded = 1;
+                       width = -width;
                } else {
+                       left_padded = 0;
+               }
+               if (*format == '.') {
                        format++;
-                       if (*format == '%' || *format == 0) {
-                               addchar('%');
-                               if (*format == '%')
-                                       format++;
+                       if (*format == '*') {
+                               format++;
+                               if (pos >= argc)
+                                       m4errx(1, 
+                                           "Format with too many format specifiers.");
+                               extra = strtol(argv[pos++], NULL, 10);
                        } else {
-                           int left_padded = 0;
-                           unsigned long width;
-                           size_t l;
-
-                           if (*format == '-') {
-                                   left_padded = 1;
-                                   format++;
-                           }
-                           width = strtoul(format, (char **)&format, 10);
-                           if (*format != 's') {
-                                   m4errx(1, "Unsupported format specification: %s.", argv[2]);
-                           }
-                           format++;
-                           if (pos >= argc)
-                                   m4errx(1, "Format with too many values.");
-                           l = strlen(argv[pos]);
-                           if (!left_padded) {
-                                   while (l < width--)
-                                           addchar(' ');
-                           }
-                           addchars(argv[pos++], l);
-                           if (left_padded) {
-                                   while (l < width--)
-                                           addchar(' ');
-                           }
+                               extra = strtol(format, (char **)&format, 10);
                        }
+               } else {
+                       extra = LONG_MAX;
+               }
+               if (pos >= argc)
+                       m4errx(1, "Format with too many format specifiers.");
+               switch(*format) {
+               case 's':
+                       thisarg = argv[pos++];
+                       break;
+               case 'c':
+                       temp[0] = strtoul(argv[pos++], NULL, 10);
+                       temp[1] = 0;
+                       thisarg = temp;
+                       break;
+               default:
+                       m4errx(1, "Unsupported format specification: %s.", 
+                           argv[2]);
+               }
+               format++;
+               l = strlen(thisarg);
+               if (l > extra)
+                       l = extra;
+               if (!left_padded) {
+                       while (l < width--)
+                               addchar(' ');
+               }
+               addchars(thisarg, l);
+               if (left_padded) {
+                       while (l < width--)
+                               addchar(' ');
                }
        }
        pbstr(getstring());
index 1b637bb..8f75066 100644 (file)
@@ -1,4 +1,4 @@
-.\"    @(#) $OpenBSD: m4.1,v 1.50 2007/05/31 19:20:12 jmc Exp $
+.\"    @(#) $OpenBSD: m4.1,v 1.51 2008/08/16 12:21:46 espie Exp $
 .\"
 .\" Copyright (c) 1989, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -30,7 +30,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: August 16 2008 $
 .Dt M4 1
 .Os
 .Sh NAME
@@ -138,7 +138,11 @@ Activate GNU-m4 compatibility mode.
 In this mode, translit handles simple character
 ranges (e.g., a-z), regular expressions mimic emacs behavior,
 multiple m4wrap calls are handled as a stack,
-and the number of diversions is unlimited.
+the number of diversions is unlimited,
+empty names for macro definitions are allowed,
+and eval understands 
+.Sq 0rbase:value 
+numbers.
 .It Fl I Ar "dirname"
 Add directory
 .Ar dirname
@@ -268,9 +272,9 @@ with escape sequences substituted with
 .Fa arg1
 and following arguments, in a way similar to
 .Xr printf 3 .
-This built-in is only available in GNU-m4 compatibility mode, and the
-left-padding flag, an optional field width and the %s data type
-are the only supported parameters.
+This built-in is only available in GNU-m4 compatibility mode, and the only
+parameters implemented are there for autoconf compatibility:
+left-padding flag, an optional field width, a maximum field width, *-specified field widths, and the %s and %c data type.
 .It Fn ifdef name yes no
 If the macro named by the first argument is defined then return the second
 argument, otherwise the third.
index b85ac98..377af13 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: main.c,v 1.75 2008/08/16 12:19:49 espie Exp $ */
+/*     $OpenBSD: main.c,v 1.76 2008/08/16 12:21:46 espie Exp $ */
 /*     $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $    */
 
 /*-
@@ -428,8 +428,9 @@ macro(void)
                case LPAREN:
                        if (PARLEV > 0)
                                chrsave(t);
-                       while (isspace(l = gpbc()))
-                               ;               /* skip blank, tab, nl.. */
+                       while (isspace(l = gpbc())) /* skip blank, tab, nl.. */
+                               if (PARLEV > 0)
+                                       chrsave(l);
                        pushback(l);
                        record(paren, PARLEV++);
                        break;
index eca4707..67dc778 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: misc.c,v 1.37 2007/05/05 03:42:49 ray Exp $   */
+/*     $OpenBSD: misc.c,v 1.38 2008/08/16 12:21:46 espie Exp $ */
 /*     $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $     */
 
 /*
@@ -54,11 +54,11 @@ char *endest;               /* end of string space         */
 static size_t strsize = STRSPMAX;
 static size_t bufsize = BUFSIZE;
 
-char *buf;                     /* push-back buffer            */
-char *bufbase;                 /* the base for current ilevel */
-char *bbase[MAXINP];           /* the base for each ilevel    */
-char *bp;                      /* first available character   */
-char *endpbb;                  /* end of push-back buffer     */
+unsigned char *buf;                    /* push-back buffer            */
+unsigned char *bufbase;                        /* the base for current ilevel */
+unsigned char *bbase[MAXINP];          /* the base for each ilevel    */
+unsigned char *bp;                     /* first available character   */
+unsigned char *endpbb;                 /* end of push-back buffer     */
 
 
 /*
@@ -163,7 +163,7 @@ initspaces()
        strspace = xalloc(strsize+1, NULL);
        ep = strspace;
        endest = strspace+strsize;
-       buf = (char *)xalloc(bufsize, NULL);
+       buf = (unsigned char *)xalloc(bufsize, NULL);
        bufbase = buf;
        bp = buf;
        endpbb = buf + bufsize;
@@ -195,7 +195,7 @@ enlarge_strspace()
 void
 enlarge_bufspace()
 {
-       char *newbuf;
+       unsigned char *newbuf;
        int i;
 
        bufsize += bufsize/2;
@@ -418,7 +418,7 @@ buffer_mark()
 void
 dump_buffer(FILE *f, size_t m)
 {
-       char *s;
+       unsigned char *s;
 
        for (s = bp; s-buf > m;)
                fputc(*--s, f);
index 7ab4020..a67af95 100644 (file)
@@ -1,5 +1,5 @@
 %{
-/* $OpenBSD: parser.y,v 1.3 2006/01/20 23:10:19 espie Exp $ */
+/* $OpenBSD: parser.y,v 1.4 2008/08/16 12:21:46 espie Exp $ */
 /*
  * Copyright (c) 2004 Marc Espie <espie@cvs.openbsd.org>
  *
@@ -22,6 +22,7 @@ extern int yylex(void);
 extern int yyerror(const char *);
 %}
 %token NUMBER
+%token ERROR
 %left LOR
 %left LAND
 %left '|'
index 895ea5c..10de9a3 100644 (file)
@@ -1,5 +1,5 @@
 %{
-/* $OpenBSD: tokenizer.l,v 1.3 2006/01/20 23:10:19 espie Exp $ */
+/* $OpenBSD: tokenizer.l,v 1.4 2008/08/16 12:21:46 espie Exp $ */
 /*
  * Copyright (c) 2004 Marc Espie <espie@cvs.openbsd.org>
  *
 #include <stdint.h>
 #include <limits.h>
 
+extern int mimic_gnu;
 extern int32_t yylval;
 
 int32_t number(void);
+int32_t parse_radix(void);
 %}
 
 delim  [ \t\n]
@@ -31,10 +33,17 @@ ws  {delim}+
 hex    0[xX][0-9a-fA-F]+
 oct    0[0-7]*
 dec    [1-9][0-9]*
+radix  0[rR][0-9]+:[0-9a-zA-Z]+
 
 %%
 {ws}                   {/* just skip it */}
 {hex}|{oct}|{dec}      { yylval = number(); return(NUMBER); }
+{radix}                        { if (mimic_gnu) {
+                               yylval = parse_radix(); return(NUMBER);
+                         } else {
+                               return(ERROR);
+                         }
+                       }
 "<="                   { return(LE); }
 ">="                   { return(GE); }
 "<<"                   { return(LSHIFT); }
@@ -58,5 +67,31 @@ number()
                fprintf(stderr, "m4: numeric overflow in expr: %s\n", yytext);
        }
        return l;
+}
+
+int32_t
+parse_radix()
+{
+       long base;
+       char *next;
+       long l;
 
+       l = 0;
+       base = strtol(yytext+2, &next, 0);
+       if (base > 36 || next == NULL) {
+               fprintf(stderr, "m4: error in number %s\n", yytext);
+       } else {
+               next++;
+               while (*next != 0) {
+                       if (*next >= '0' && *next <= '9')
+                               l = base * l + *next - '0';
+                       else if (*next >= 'a' && *next <= 'z')
+                               l = base * l + *next - 'a' + 10;
+                       else if (*next >= 'A' && *next <= 'Z')
+                               l = base * l + *next - 'A' + 10;
+                       next++;
+               }
+       }
+       return l;
 }
+