]> git.cameronkatri.com Git - mandoc.git/blobdiff - macro.c
Memory-corruption fix.
[mandoc.git] / macro.c
diff --git a/macro.c b/macro.c
index 30518a7ebd9af16c11260d1090ce514b26232faa..ea4af29bb5cbeecd82597c3cb95f6fa0085f7f60 100644 (file)
--- a/macro.c
+++ b/macro.c
@@ -1,4 +1,4 @@
-/* $Id: macro.c,v 1.55 2009/02/28 20:13:06 kristaps Exp $ */
+/* $Id: macro.c,v 1.58 2009/03/08 11:41:22 kristaps Exp $ */
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
 /*
  * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -66,7 +66,6 @@ static        int       perr(struct mdoc *, int, int, int);
 
 #define        ENOCTX          (1)
 #define        ENOPARMS        (2)
 
 #define        ENOCTX          (1)
 #define        ENOPARMS        (2)
-#define        EARGVLIM        (3)
 
 /* Central table of library: who gets parsed how. */
 
 
 /* Central table of library: who gets parsed how. */
 
@@ -179,6 +178,7 @@ const       struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
        { macro_constant, 0 }, /* Hf */
        { macro_obsolete, 0 }, /* Fr */
        { macro_constant, 0 }, /* Ud */
        { macro_constant, 0 }, /* Hf */
        { macro_obsolete, 0 }, /* Fr */
        { macro_constant, 0 }, /* Ud */
+       { macro_constant, 0 }, /* Lb */
 };
 
 const  struct mdoc_macro * const mdoc_macros = __mdoc_macros;
 };
 
 const  struct mdoc_macro * const mdoc_macros = __mdoc_macros;
@@ -198,11 +198,6 @@ perr(struct mdoc *mdoc, int line, int pos, int type)
                c = mdoc_perr(mdoc, line, pos, 
                                "macro doesn't expect parameters");
                break;
                c = mdoc_perr(mdoc, line, pos, 
                                "macro doesn't expect parameters");
                break;
-       case (EARGVLIM):
-               c = mdoc_perr(mdoc, line, pos, 
-                               "argument hard-limit %d reached",
-                               MDOC_LINEARG_MAX);
-               break;
        default:
                abort();
                /* NOTREACHED */
        default:
                abort();
                /* NOTREACHED */
@@ -237,7 +232,7 @@ lookup(struct mdoc *mdoc, int line, int pos, int from, const char *p)
 {
        int              res;
 
 {
        int              res;
 
-       res = mdoc_find(mdoc, p);
+       res = mdoc_tokhash_find(mdoc->htab, p);
        if (MDOC_PARSED & mdoc_macros[from].flags)
                return(res);
        if (MDOC_MAX == res)
        if (MDOC_PARSED & mdoc_macros[from].flags)
                return(res);
        if (MDOC_MAX == res)
@@ -517,7 +512,9 @@ rewind_subblock(enum mdoc_type type, struct mdoc *mdoc,
                        break;
                else if (rewind_dobreak(tok, n))
                        continue;
                        break;
                else if (rewind_dobreak(tok, n))
                        continue;
-               return(mdoc_perr(mdoc, line, ppos, "scope breaks prior %s", mdoc_node2a(n)));
+               return(mdoc_perr(mdoc, line, ppos, 
+                       "scope breaks %s", MDOC_ROOT == n->type ?
+                       "<root>" : mdoc_macronames[n->tok]));
        }
 
        assert(n);
        }
 
        assert(n);
@@ -541,8 +538,8 @@ rewind_expblock(struct mdoc *mdoc, int tok, int line, int ppos)
                else if (rewind_dobreak(tok, n))
                        continue;
                return(mdoc_perr(mdoc, line, ppos, 
                else if (rewind_dobreak(tok, n))
                        continue;
                return(mdoc_perr(mdoc, line, ppos, 
-                                       "scope breaks prior %s", 
-                                       mdoc_node2a(n)));
+                       "scope breaks %s", MDOC_ROOT == n->type ?
+                       "<root>" : mdoc_macronames[n->tok]));
        }
 
        assert(n);
        }
 
        assert(n);
@@ -566,8 +563,8 @@ rewind_impblock(struct mdoc *mdoc, int tok, int line, int ppos)
                else if (rewind_dobreak(tok, n))
                        continue;
                return(mdoc_perr(mdoc, line, ppos, 
                else if (rewind_dobreak(tok, n))
                        continue;
                return(mdoc_perr(mdoc, line, ppos, 
-                                       "scope breaks prior %s", 
-                                       mdoc_node2a(n)));
+                       "scope breaks %s", MDOC_ROOT == n->type ?
+                       "<root>" : mdoc_macronames[n->tok]));
        }
 
        assert(n);
        }
 
        assert(n);
@@ -723,16 +720,17 @@ macro_scoped_close(MACRO_PROT_ARGS)
 static int
 macro_text(MACRO_PROT_ARGS)
 {
 static int
 macro_text(MACRO_PROT_ARGS)
 {
-       int               la, lastpunct, c, w, argc;
-       struct mdoc_arg   argv[MDOC_LINEARG_MAX];
+       int               la, lastpunct, c, w;
+       struct mdoc_arg  *arg;
        char             *p;
 
        la = ppos;
        lastpunct = 0;
        char             *p;
 
        la = ppos;
        lastpunct = 0;
+       arg = NULL;
 
 
-       for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
+       for (;;) {
                la = *pos;
                la = *pos;
-               c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
+               c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
                if (ARGV_EOLN == c)
                        break;
                if (ARGV_WORD == c) {
                if (ARGV_EOLN == c)
                        break;
                if (ARGV_WORD == c) {
@@ -740,23 +738,12 @@ macro_text(MACRO_PROT_ARGS)
                        break;
                } else if (ARGV_ARG == c)
                        continue;
                        break;
                } else if (ARGV_ARG == c)
                        continue;
-
-               mdoc_argv_free(argc, argv);
+               mdoc_argv_free(arg);
                return(0);
        }
 
                return(0);
        }
 
-       if (MDOC_LINEARG_MAX == argc) {
-               mdoc_argv_free(argc - 1, argv);
-               return(perr(mdoc, line, ppos, EARGVLIM));
-       }
-
-       c = mdoc_elem_alloc(mdoc, line, ppos, 
-                       tok, (size_t)argc, argv);
-
-       if (0 == c) {
-               mdoc_argv_free(argc, argv);
+       if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
                return(0);
                return(0);
-       }
 
        mdoc->next = MDOC_NEXT_CHILD;
 
 
        mdoc->next = MDOC_NEXT_CHILD;
 
@@ -766,11 +753,8 @@ macro_text(MACRO_PROT_ARGS)
                w = mdoc_args(mdoc, line, pos, buf, tok, &p);
                assert(ARGS_PHRASE != c);
 
                w = mdoc_args(mdoc, line, pos, buf, tok, &p);
                assert(ARGS_PHRASE != c);
 
-               if (ARGS_ERROR == w) {
-                       mdoc_argv_free(argc, argv);
+               if (ARGS_ERROR == w)
                        return(0);
                        return(0);
-               }
-
                if (ARGS_EOLN == w)
                        break;
                if (ARGS_PUNCT == w)
                if (ARGS_EOLN == w)
                        break;
                if (ARGS_PUNCT == w)
@@ -780,37 +764,29 @@ macro_text(MACRO_PROT_ARGS)
                        lookup(mdoc, line, la, tok, p);
 
                if (MDOC_MAX != c && -1 != c) {
                        lookup(mdoc, line, la, tok, p);
 
                if (MDOC_MAX != c && -1 != c) {
-                       if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
-                               mdoc_argv_free(argc, argv);
+                       if (0 == lastpunct && ! rewind_elem(mdoc, tok))
                                return(0);
                                return(0);
-                       }
-                       mdoc_argv_free(argc, argv);
                        c = mdoc_macro(mdoc, c, line, la, pos, buf);
                        if (0 == c)
                                return(0);
                        if (ppos > 1)
                                return(1);
                        return(append_delims(mdoc, line, pos, buf));
                        c = mdoc_macro(mdoc, c, line, la, pos, buf);
                        if (0 == c)
                                return(0);
                        if (ppos > 1)
                                return(1);
                        return(append_delims(mdoc, line, pos, buf));
-               } else if (-1 == c) {
-                       mdoc_argv_free(argc, argv);
+               } else if (-1 == c)
                        return(0);
                        return(0);
-               }
 
                /* FIXME: .Fl and .Ar handling of `|'. */
 
                if (ARGS_QWORD != w && mdoc_isdelim(p)) {
 
                /* FIXME: .Fl and .Ar handling of `|'. */
 
                if (ARGS_QWORD != w && mdoc_isdelim(p)) {
-                       if (0 == lastpunct && ! rewind_elem(mdoc, tok)) {
-                               mdoc_argv_free(argc, argv);
+                       if (0 == lastpunct && ! rewind_elem(mdoc, tok))
                                return(0);
                                return(0);
-                       }
                        lastpunct = 1;
                } else if (lastpunct) {
                        lastpunct = 1;
                } else if (lastpunct) {
-                       c = mdoc_elem_alloc(mdoc, line, ppos, 
-                                       tok, (size_t)argc, argv);
-                       if (0 == c) {
-                               mdoc_argv_free(argc, argv);
+                       c = mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
+
+                       if (0 == c)
                                return(0);
                                return(0);
-                       }
+
                        mdoc->next = MDOC_NEXT_CHILD;
                        lastpunct = 0;
                }
                        mdoc->next = MDOC_NEXT_CHILD;
                        lastpunct = 0;
                }
@@ -820,8 +796,6 @@ macro_text(MACRO_PROT_ARGS)
                mdoc->next = MDOC_NEXT_SIBLING;
        }
 
                mdoc->next = MDOC_NEXT_SIBLING;
        }
 
-       mdoc_argv_free(argc, argv);
-
        if (0 == lastpunct && ! rewind_elem(mdoc, tok))
                return(0);
        if (ppos > 1)
        if (0 == lastpunct && ! rewind_elem(mdoc, tok))
                return(0);
        if (ppos > 1)
@@ -857,8 +831,8 @@ macro_text(MACRO_PROT_ARGS)
 static int
 macro_scoped(MACRO_PROT_ARGS)
 {
 static int
 macro_scoped(MACRO_PROT_ARGS)
 {
-       int               c, lastarg, argc;
-       struct mdoc_arg   argv[MDOC_LINEARG_MAX];
+       int               c, lastarg;
+       struct mdoc_arg  *arg;
        char             *p;
 
        assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
        char             *p;
 
        assert ( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
@@ -873,10 +847,12 @@ macro_scoped(MACRO_PROT_ARGS)
        }
 
        /* Parse arguments. */
        }
 
        /* Parse arguments. */
+       
+       arg = NULL;
 
 
-       for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
+       for (;;) {
                lastarg = *pos;
                lastarg = *pos;
-               c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
+               c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
                if (ARGV_EOLN == c)
                        break;
                if (ARGV_WORD == c) {
                if (ARGV_EOLN == c)
                        break;
                if (ARGV_WORD == c) {
@@ -884,20 +860,11 @@ macro_scoped(MACRO_PROT_ARGS)
                        break;
                } else if (ARGV_ARG == c)
                        continue;
                        break;
                } else if (ARGV_ARG == c)
                        continue;
-               mdoc_argv_free(argc, argv);
+               mdoc_argv_free(arg);
                return(0);
        }
 
                return(0);
        }
 
-       if (MDOC_LINEARG_MAX == argc) {
-               mdoc_argv_free(argc - 1, argv);
-               return(perr(mdoc, line, ppos, EARGVLIM));
-       }
-
-       c = mdoc_block_alloc(mdoc, line, ppos, 
-                       tok, (size_t)argc, argv);
-       mdoc_argv_free(argc, argv);
-
-       if (0 == c)
+       if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, arg))
                return(0);
 
        mdoc->next = MDOC_NEXT_CHILD;
                return(0);
 
        mdoc->next = MDOC_NEXT_CHILD;
@@ -990,7 +957,7 @@ macro_scoped_line(MACRO_PROT_ARGS)
        int               lastarg, c;
        char              *p;
 
        int               lastarg, c;
        char              *p;
 
-       if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
+       if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
                return(0);
        mdoc->next = MDOC_NEXT_CHILD;
 
                return(0);
        mdoc->next = MDOC_NEXT_CHILD;
 
@@ -1074,7 +1041,7 @@ macro_constant_scoped(MACRO_PROT_ARGS)
                break;
        }
 
                break;
        }
 
-       if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, 0, NULL))
+       if ( ! mdoc_block_alloc(mdoc, line, ppos, tok, NULL))
                return(0); 
        mdoc->next = MDOC_NEXT_CHILD;
 
                return(0); 
        mdoc->next = MDOC_NEXT_CHILD;
 
@@ -1177,13 +1144,18 @@ macro_constant_scoped(MACRO_PROT_ARGS)
 static int
 macro_constant_delimited(MACRO_PROT_ARGS)
 {
 static int
 macro_constant_delimited(MACRO_PROT_ARGS)
 {
-       int               lastarg, flushed, j, c, maxargs, argc,
-                         igndelim;
-       struct mdoc_arg   argv[MDOC_LINEARG_MAX];
+       int               lastarg, flushed, j, c, maxargs, 
+                         igndelim, ignargs;
+       struct mdoc_arg  *arg;
        char             *p;
 
        lastarg = ppos;
        flushed = 0;
        char             *p;
 
        lastarg = ppos;
        flushed = 0;
+       
+       /* 
+        * Maximum arguments per macro.  Some of these have none and
+        * exit as soon as they're parsed.
+        */
 
        switch (tok) {
        case (MDOC_No):
 
        switch (tok) {
        case (MDOC_No):
@@ -1191,8 +1163,6 @@ macro_constant_delimited(MACRO_PROT_ARGS)
        case (MDOC_Ns):
                /* FALLTHROUGH */
        case (MDOC_Ux):
        case (MDOC_Ns):
                /* FALLTHROUGH */
        case (MDOC_Ux):
-               /* FALLTHROUGH */
-       case (MDOC_St):
                maxargs = 0;
                break;
        default:
                maxargs = 0;
                break;
        default:
@@ -1200,6 +1170,12 @@ macro_constant_delimited(MACRO_PROT_ARGS)
                break;
        }
 
                break;
        }
 
+       /* 
+        * Whether to ignore delimiter characters.  `Pf' accepts its
+        * first token as a parameter no matter what it looks like (if
+        * it's text).
+        */
+
        switch (tok) {
        case (MDOC_Pf):
                igndelim = 1;
        switch (tok) {
        case (MDOC_Pf):
                igndelim = 1;
@@ -1209,31 +1185,38 @@ macro_constant_delimited(MACRO_PROT_ARGS)
                break;
        }
 
                break;
        }
 
-       for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
-               lastarg = *pos;
-               c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
-               if (ARGV_EOLN == c)
-                       break;
-               if (ARGV_WORD == c) {
-                       *pos = lastarg;
-                       break;
-               } else if (ARGV_ARG == c)
-                       continue;
-               mdoc_argv_free(argc, argv);
-               return(0);
-       }
+       /* 
+        * Whether to ignore arguments: `St', for example, handles its
+        * argument-like parameters as regular parameters.
+        */
 
 
-       if (MDOC_LINEARG_MAX == argc) {
-               mdoc_argv_free(argc - 1, argv);
-               return(perr(mdoc, line, ppos, EARGVLIM));
+       switch (tok) {
+       case (MDOC_St):
+               ignargs = 1;
+               break;
+       default:
+               ignargs = 0;
+               break;
        }
 
        }
 
-       c = mdoc_elem_alloc(mdoc, line, ppos, 
-                       tok, (size_t)argc, argv);
-
-       mdoc_argv_free(argc, argv);
+       arg = NULL;
+
+       if ( ! ignargs)
+               for (;;) {
+                       lastarg = *pos;
+                       c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
+                       if (ARGV_EOLN == c)
+                               break;
+                       if (ARGV_WORD == c) {
+                               *pos = lastarg;
+                               break;
+                       } else if (ARGV_ARG == c)
+                               continue;
+                       mdoc_argv_free(arg);
+                       return(0);
+               }
 
 
-       if (0 == c)
+       if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
                return(0);
 
        mdoc->next = MDOC_NEXT_CHILD;
                return(0);
 
        mdoc->next = MDOC_NEXT_CHILD;
@@ -1295,15 +1278,17 @@ macro_constant_delimited(MACRO_PROT_ARGS)
 static int
 macro_constant(MACRO_PROT_ARGS)
 {
 static int
 macro_constant(MACRO_PROT_ARGS)
 {
-       int               c, w, la, argc;
-       struct mdoc_arg   argv[MDOC_LINEARG_MAX];
+       int               c, w, la;
+       struct mdoc_arg  *arg;
        char             *p;
 
        assert( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
 
        char             *p;
 
        assert( ! (MDOC_CALLABLE & mdoc_macros[tok].flags));
 
-       for (argc = 0; argc < MDOC_LINEARG_MAX; argc++) {
+       arg = NULL;
+
+       for (;;) {
                la = *pos;
                la = *pos;
-               c = mdoc_argv(mdoc, line, tok, &argv[argc], pos, buf);
+               c = mdoc_argv(mdoc, line, tok, &arg, pos, buf);
                if (ARGV_EOLN == c) 
                        break;
                if (ARGV_WORD == c) {
                if (ARGV_EOLN == c) 
                        break;
                if (ARGV_WORD == c) {
@@ -1311,22 +1296,11 @@ macro_constant(MACRO_PROT_ARGS)
                        break;
                } else if (ARGV_ARG == c)
                        continue;
                        break;
                } else if (ARGV_ARG == c)
                        continue;
-
-               mdoc_argv_free(argc, argv);
+               mdoc_argv_free(arg);
                return(0);
        }
 
                return(0);
        }
 
-       if (MDOC_LINEARG_MAX == argc) {
-               mdoc_argv_free(argc - 1, argv);
-               return(perr(mdoc, line, ppos, EARGVLIM));
-       }
-
-       c = mdoc_elem_alloc(mdoc, line, ppos, 
-                       tok, (size_t)argc, argv);
-
-       mdoc_argv_free(argc, argv);
-
-       if (0 == c)
+       if ( ! mdoc_elem_alloc(mdoc, line, ppos, tok, arg))
                return(0);
 
        mdoc->next = MDOC_NEXT_CHILD;
                return(0);
 
        mdoc->next = MDOC_NEXT_CHILD;