]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdoc_argv.c
Scaling factor made floating point (as per groff.7) and, e.g., gnu/usr.bin/cvs/man...
[mandoc.git] / mdoc_argv.c
index 287913f6057feccb69c423fa4dbe5ef5df29f987..4a30cff0529d438df63e1bc7374834234ae86736 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_argv.c,v 1.18 2009/07/18 18:59:33 kristaps Exp $ */
+/*     $Id: mdoc_argv.c,v 1.27 2009/10/07 14:52:35 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
  * There's no limit to the number or arguments that may be allocated.
  */
 
-/* FIXME .Bf Li raises "macro-like parameter". */
-
-#define        ARGS_DELIM      (1 << 1)
-#define        ARGS_TABSEP     (1 << 2)
-
 #define        ARGV_NONE       (1 << 0)
 #define        ARGV_SINGLE     (1 << 1)
 #define        ARGV_MULTI      (1 << 2)
@@ -65,7 +60,7 @@ static        int mdoc_argvflags[MDOC_ARG_MAX] = {
        ARGV_NONE,      /* MDOC_Unfilled */
        ARGV_NONE,      /* MDOC_Literal */
        ARGV_NONE,      /* MDOC_File */
-       ARGV_SINGLE,    /* MDOC_Offset */
+       ARGV_OPT_SINGLE, /* MDOC_Offset */
        ARGV_NONE,      /* MDOC_Bullet */
        ARGV_NONE,      /* MDOC_Dash */
        ARGV_NONE,      /* MDOC_Hyphen */
@@ -79,7 +74,7 @@ static        int mdoc_argvflags[MDOC_ARG_MAX] = {
        ARGV_MULTI,     /* MDOC_Column */
        ARGV_SINGLE,    /* MDOC_Width */
        ARGV_NONE,      /* MDOC_Compact */
-       ARGV_OPT_SINGLE, /* MDOC_Std */
+       ARGV_NONE,      /* MDOC_Std */
        ARGV_NONE,      /* MDOC_Filled */
        ARGV_NONE,      /* MDOC_Words */
        ARGV_NONE,      /* MDOC_Emphasis */
@@ -314,9 +309,13 @@ mdoc_argv_free(struct mdoc_arg *p)
        for (i = 0; i < (int)p->argc; i++) {
                if (0 == p->argv[i].sz)
                        continue;
+               if (NULL == p->argv[i].value)
+                       continue;
+
                /* LINTED */
                for (j = 0; j < (int)p->argv[i].sz; j++) 
-                       free(p->argv[i].value[j]);
+                       if (p->argv[i].value[j])
+                               free(p->argv[i].value[j]);
 
                free(p->argv[i].value);
        }
@@ -326,6 +325,15 @@ mdoc_argv_free(struct mdoc_arg *p)
 }
 
 
+int
+mdoc_zargs(struct mdoc *m, int line, int *pos, 
+               char *buf, int flags, char **v)
+{
+
+       return(args(m, line, pos, buf, flags, v));
+}
+
+
 int
 mdoc_args(struct mdoc *m, int line, 
                int *pos, char *buf, int tok, char **v)
@@ -371,6 +379,21 @@ args(struct mdoc *m, int line, int *pos,
        int               i;
        char             *p, *pp;
 
+       /*
+        * Parse out the terms (like `val' in `.Xx -arg val' or simply
+        * `.Xx val'), which can have all sorts of properties:
+        *
+        *   ARGS_DELIM: use special handling if encountering trailing
+        *   delimiters in the form of [[::delim::][ ]+]+.
+        *
+        *   ARGS_NOWARN: don't post warnings.  This is only used when
+        *   re-parsing delimiters, as the warnings have already been
+        *   posted.
+        *
+        *   ARGS_TABSEP: use special handling for tab/`Ta' separated
+        *   phrases like in `Bl -column'.
+        */
+
        assert(*pos);
        assert(' ' != buf[*pos]);
 
@@ -395,10 +418,14 @@ args(struct mdoc *m, int line, int *pos,
                                i++;
                }
 
-               /* FIXME: warn about trailing whitespace. */
-
                if (0 == buf[i]) {
                        *v = &buf[*pos];
+                       if (' ' != buf[i - 1])
+                               return(ARGS_PUNCT);
+                       if (ARGS_NOWARN & fl)
+                               return(ARGS_PUNCT);
+                       if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
+                               return(ARGS_ERROR);
                        return(ARGS_PUNCT);
                }
        }
@@ -413,7 +440,7 @@ args(struct mdoc *m, int line, int *pos,
         */
 
        if (ARGS_TABSEP & fl) {
-               /* Scan ahead to unescaped tab. */
+               /* Scan ahead to tab (can't be escaped). */
                p = strchr(*v, '\t');
 
                /* Scan ahead to unescaped `Ta'. */
@@ -426,59 +453,40 @@ args(struct mdoc *m, int line, int *pos,
                                break;
                }
 
-               /* Choose delimiter tab/Ta. */
-               if (p && pp)
-                       p = (p < pp ? p : pp);
-               else if ( ! p && pp)
+               /* 
+                * Adjust new-buffer position to be beyond delimiter
+                * mark (e.g., Ta -> end + 2).
+                */
+               if (p && pp) {
+                       *pos += pp < p ? 2 : 1;
+                       p = pp < p ? pp : p;
+               } else if (p && ! pp) {
+                       *pos += 1;
+               } else if (pp && ! p) {
                        p = pp;
+                       *pos += 2;
+               } else
+                       p = strchr(*v, 0);
 
-               /* Strip delimiter's preceding whitespace. */
-               /* FIXME: escaped whitespace? */
-               if (p && p > *v) {
-                       pp = p - 1;
-                       while (pp > *v && ' ' == *pp)
-                               pp--;
-                       if (pp == *v && ' ' == *pp) 
-                               *pp = 0;
-                       else if (' ' == *pp)
-                               *(pp + 1) = 0;
-               }
-
-               /* ...in- and proceding whitespace. */
-               if (p && ('\t' != *p)) {
-                       *p++ = 0;
-                       *p++ = 0;
-               } else if (p)
-                       *p++ = 0;
-
-               if (p) {
-                       while (' ' == *p)
-                               p++;
-                       if (0 != *p)
-                               *(p - 1) = 0;
-                       *pos += (int)(p - *v);
-               } 
-
-               /* Some warnings, if applicable. */
-               if (p && 0 == *p)
-                       if ( ! mdoc_pwarn(m, line, *pos, ECOLEMPTY))
-                               return(ARGS_ERROR);
-               if (p && 0 == *p && p > *v && ' ' == *(p - 1))
+               /* Whitespace check for eoln case... */
+               if (0 == *p && ' ' == *(p - 1) && ! (ARGS_NOWARN & fl))
                        if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
                                return(ARGS_ERROR);
 
-               /* Non-eoln case returns now. */
-               if (p)
-                       return(ARGS_PHRASE);
+               *pos += (int)(p - *v);
 
-               /* Configure the eoln case, too. */
-               p = strchr(*v, 0);
-               assert(p);
+               /* Strip delimiter's preceding whitespace. */
+               pp = p - 1;
+               while (pp > *v && ' ' == *pp) {
+                       if (pp > *v && '\\' == *(pp - 1))
+                               break;
+                       pp--;
+               }
+               *(pp + 1) = 0;
 
-               if (p > *v && ' ' == *(p - 1))
-                       if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
-                               return(ARGS_ERROR);
-               *pos += (int)(p - *v);
+               /* Strip delimiter's proceeding whitespace. */
+               for (pp = &buf[*pos]; ' ' == *pp; pp++, (*pos)++)
+                       /* Skip ahead. */ ;
 
                return(ARGS_PHRASE);
        } 
@@ -501,6 +509,8 @@ args(struct mdoc *m, int line, int *pos,
                }
 
                if (0 == buf[*pos]) {
+                       if (ARGS_NOWARN & fl)
+                               return(ARGS_QWORD);
                        if ( ! mdoc_pwarn(m, line, *pos, EQUOTTERM))
                                return(ARGS_ERROR);
                        return(ARGS_QWORD);
@@ -514,7 +524,7 @@ args(struct mdoc *m, int line, int *pos,
                while (' ' == buf[*pos])
                        (*pos)++;
 
-               if (0 == buf[*pos])
+               if (0 == buf[*pos] && ! (ARGS_NOWARN & fl))
                        if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
                                return(ARGS_ERROR);
 
@@ -538,7 +548,7 @@ args(struct mdoc *m, int line, int *pos,
        while (' ' == buf[*pos])
                (*pos)++;
 
-       if (0 == buf[*pos])
+       if (0 == buf[*pos] && ! (ARGS_NOWARN & fl))
                if ( ! mdoc_pwarn(m, line, *pos, ETAILWS))
                        return(ARGS_ERROR);
 
@@ -547,7 +557,7 @@ args(struct mdoc *m, int line, int *pos,
 
 
 static int
-argv_a2arg(int tok, const char *argv)
+argv_a2arg(int tok, const char *p)
 {
 
        /*
@@ -560,80 +570,80 @@ argv_a2arg(int tok, const char *argv)
 
        switch (tok) {
        case (MDOC_An):
-               if (0 == strcmp(argv, "split"))
+               if (0 == strcmp(p, "split"))
                        return(MDOC_Split);
-               else if (0 == strcmp(argv, "nosplit"))
+               else if (0 == strcmp(p, "nosplit"))
                        return(MDOC_Nosplit);
                break;
 
        case (MDOC_Bd):
-               if (0 == strcmp(argv, "ragged"))
+               if (0 == strcmp(p, "ragged"))
                        return(MDOC_Ragged);
-               else if (0 == strcmp(argv, "unfilled"))
+               else if (0 == strcmp(p, "unfilled"))
                        return(MDOC_Unfilled);
-               else if (0 == strcmp(argv, "filled"))
+               else if (0 == strcmp(p, "filled"))
                        return(MDOC_Filled);
-               else if (0 == strcmp(argv, "literal"))
+               else if (0 == strcmp(p, "literal"))
                        return(MDOC_Literal);
-               else if (0 == strcmp(argv, "file"))
+               else if (0 == strcmp(p, "file"))
                        return(MDOC_File);
-               else if (0 == strcmp(argv, "offset"))
+               else if (0 == strcmp(p, "offset"))
                        return(MDOC_Offset);
-               else if (0 == strcmp(argv, "compact"))
+               else if (0 == strcmp(p, "compact"))
                        return(MDOC_Compact);
                break;
 
        case (MDOC_Bf):
-               if (0 == strcmp(argv, "emphasis"))
+               if (0 == strcmp(p, "emphasis"))
                        return(MDOC_Emphasis);
-               else if (0 == strcmp(argv, "literal"))
+               else if (0 == strcmp(p, "literal"))
                        return(MDOC_Literal);
-               else if (0 == strcmp(argv, "symbolic"))
+               else if (0 == strcmp(p, "symbolic"))
                        return(MDOC_Symbolic);
                break;
 
        case (MDOC_Bk):
-               if (0 == strcmp(argv, "words"))
+               if (0 == strcmp(p, "words"))
                        return(MDOC_Words);
                break;
 
        case (MDOC_Bl):
-               if (0 == strcmp(argv, "bullet"))
+               if (0 == strcmp(p, "bullet"))
                        return(MDOC_Bullet);
-               else if (0 == strcmp(argv, "dash"))
+               else if (0 == strcmp(p, "dash"))
                        return(MDOC_Dash);
-               else if (0 == strcmp(argv, "hyphen"))
+               else if (0 == strcmp(p, "hyphen"))
                        return(MDOC_Hyphen);
-               else if (0 == strcmp(argv, "item"))
+               else if (0 == strcmp(p, "item"))
                        return(MDOC_Item);
-               else if (0 == strcmp(argv, "enum"))
+               else if (0 == strcmp(p, "enum"))
                        return(MDOC_Enum);
-               else if (0 == strcmp(argv, "tag"))
+               else if (0 == strcmp(p, "tag"))
                        return(MDOC_Tag);
-               else if (0 == strcmp(argv, "diag"))
+               else if (0 == strcmp(p, "diag"))
                        return(MDOC_Diag);
-               else if (0 == strcmp(argv, "hang"))
+               else if (0 == strcmp(p, "hang"))
                        return(MDOC_Hang);
-               else if (0 == strcmp(argv, "ohang"))
+               else if (0 == strcmp(p, "ohang"))
                        return(MDOC_Ohang);
-               else if (0 == strcmp(argv, "inset"))
+               else if (0 == strcmp(p, "inset"))
                        return(MDOC_Inset);
-               else if (0 == strcmp(argv, "column"))
+               else if (0 == strcmp(p, "column"))
                        return(MDOC_Column);
-               else if (0 == strcmp(argv, "width"))
+               else if (0 == strcmp(p, "width"))
                        return(MDOC_Width);
-               else if (0 == strcmp(argv, "offset"))
+               else if (0 == strcmp(p, "offset"))
                        return(MDOC_Offset);
-               else if (0 == strcmp(argv, "compact"))
+               else if (0 == strcmp(p, "compact"))
                        return(MDOC_Compact);
-               else if (0 == strcmp(argv, "nested"))
+               else if (0 == strcmp(p, "nested"))
                        return(MDOC_Nested);
                break;
        
        case (MDOC_Rv):
                /* FALLTHROUGH */
        case (MDOC_Ex):
-               if (0 == strcmp(argv, "std"))
+               if (0 == strcmp(p, "std"))
                        return(MDOC_Std);
                break;
        default: