[BACK]Return to roff.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/roff.c between version 1.32 and 1.33

version 1.32, 2008/12/02 00:15:41 version 1.33, 2008/12/02 13:20:24
Line 17 
Line 17 
  * PERFORMANCE OF THIS SOFTWARE.   * PERFORMANCE OF THIS SOFTWARE.
  */   */
 #include <sys/param.h>  #include <sys/param.h>
   #include <sys/types.h>
   
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
Line 30 
Line 31 
 #include "libmdocml.h"  #include "libmdocml.h"
 #include "private.h"  #include "private.h"
   
   /* FIXME: First letters of quoted-text interpreted in rofffindtok. */
   /* FIXME: `No' not implemented. */
 /* TODO: warn if Pp occurs before/after Sh etc. (see mdoc.samples). */  /* TODO: warn if Pp occurs before/after Sh etc. (see mdoc.samples). */
 /* TODO: warn about "X section only" macros. */  /* TODO: warn about "X section only" macros. */
 /* TODO: warn about empty lists. */  /* TODO: warn about empty lists. */
Line 104  static int    roff_Dd(ROFFCALL_ARGS);
Line 107  static int    roff_Dd(ROFFCALL_ARGS);
 static  int               roff_Dt(ROFFCALL_ARGS);  static  int               roff_Dt(ROFFCALL_ARGS);
 static  int               roff_Os(ROFFCALL_ARGS);  static  int               roff_Os(ROFFCALL_ARGS);
 static  int               roff_Ns(ROFFCALL_ARGS);  static  int               roff_Ns(ROFFCALL_ARGS);
   static  int               roff_Sm(ROFFCALL_ARGS);
 static  int               roff_layout(ROFFCALL_ARGS);  static  int               roff_layout(ROFFCALL_ARGS);
 static  int               roff_text(ROFFCALL_ARGS);  static  int               roff_text(ROFFCALL_ARGS);
 static  int               roff_noop(ROFFCALL_ARGS);  static  int               roff_noop(ROFFCALL_ARGS);
Line 126  static int    roffnextopt(const struct rofftree *,
Line 130  static int    roffnextopt(const struct rofftree *,
                                 int, char ***, char **);                                  int, char ***, char **);
 static  int               roffparseopts(struct rofftree *, int,  static  int               roffparseopts(struct rofftree *, int,
                                 char ***, int *, char **);                                  char ***, int *, char **);
   static  int               roffcall(struct rofftree *, int, char **);
 static  int               roffparse(struct rofftree *, char *);  static  int               roffparse(struct rofftree *, char *);
 static  int               textparse(const struct rofftree *, char *);  static  int               textparse(const struct rofftree *, char *);
   
   #ifdef __linux__
   static  size_t            strlcat(char *, const char *, size_t);
   static  size_t            strlcpy(char *, const char *, size_t);
   extern  int               vsnprintf(char *, size_t,
                                   const char *, va_list);
   extern  char             *strptime(const char *, const char *,
                                   struct tm *);
   #endif
   
   
 static  const int roffarg_An[] = { ROFF_Split, ROFF_Nosplit, ROFF_ARGMAX };  static  const int roffarg_An[] = { ROFF_Split, ROFF_Nosplit, ROFF_ARGMAX };
 static  const int roffarg_Bd[] = { ROFF_Ragged, ROFF_Unfilled, ROFF_Literal,  static  const int roffarg_Bd[] = { ROFF_Ragged, ROFF_Unfilled, ROFF_Literal,
         ROFF_File, ROFF_Offset, ROFF_Filled, ROFF_Compact, ROFF_ARGMAX };          ROFF_File, ROFF_Offset, ROFF_Filled, ROFF_Compact, ROFF_ARGMAX };
Line 252  static const struct rofftok tokens[ROFF_MAX] = {
Line 266  static const struct rofftok tokens[ROFF_MAX] = {
         {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sc */          {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sc */
         {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* So */          {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* So */
         {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Sq */          {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Sq */
         {        NULL, NULL, NULL, NULL, 0, ROFF_SPECIAL, 0 }, /* Sm */          {     roff_Sm, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Sm */
         {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sx */          {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sx */
         {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */          {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */
         {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */          {   roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */
Line 818  roffnode_free(struct rofftree *tree)
Line 832  roffnode_free(struct rofftree *tree)
   
   
 static int  static int
   roffcall(struct rofftree *tree, int tok, char **argv)
   {
   
           if (NULL == tokens[tok].cb) {
                   roff_err(tree, *argv, "unsupported macro `%s'",
                                   toknames[tok]);
                   return(0);
           }
           if ( ! (*tokens[tok].cb)(tok, tree, argv, ROFF_ENTER))
                   return(0);
           return(1);
   }
   
   
   static int
 roffnextopt(const struct rofftree *tree, int tok,  roffnextopt(const struct rofftree *tree, int tok,
                 char ***in, char **val)                  char ***in, char **val)
 {  {
Line 835  roffnextopt(const struct rofftree *tree, int tok, 
Line 864  roffnextopt(const struct rofftree *tree, int tok, 
   
         if (ROFF_ARGMAX == (v = rofffindarg(arg + 1))) {          if (ROFF_ARGMAX == (v = rofffindarg(arg + 1))) {
                 roff_warn(tree, arg, "argument-like parameter `%s' to "                  roff_warn(tree, arg, "argument-like parameter `%s' to "
                                 "`%s'", &arg[1], toknames[tok]);                                  "`%s'", arg, toknames[tok]);
                 return(-1);                  return(-1);
         }          }
   
Line 1053  roff_Dt(ROFFCALL_ARGS)
Line 1082  roff_Dt(ROFFCALL_ARGS)
   
 /* ARGSUSED */  /* ARGSUSED */
 static  int  static  int
 roff_Ns(ROFFCALL_ARGS)  roff_Sm(ROFFCALL_ARGS)
 {  {
         int              j, c, first;          int              argcp[1];
           char            *argvp[1], *morep[1], *p;
   
         first = (*argv == tree->cur);          p = *argv++;
   
         argv++;          argcp[0] = ROFF_ARGMAX;
           argvp[0] = NULL;
           if (NULL == (morep[0] = *argv++)) {
                   roff_err(tree, p, "`Sm' expects an argument");
                   return(0);
           } else if (0 != strcmp(morep[0], "on") &&
                           0 != strcmp(morep[0], "off")) {
                   roff_err(tree, p, "`Sm' has invalid argument");
                   return(0);
           }
   
         if (ROFF_MAX != (c = rofffindcallable(*argv))) {          if (*argv)
                 if (NULL == tokens[c].cb) {                  roff_warn(tree, *argv, "`Sm' shouldn't have arguments");
                         roff_err(tree, *argv, "unsupported macro `%s'",  
                                         toknames[c]);  
                         return(0);  
                 }  
                 if ( ! (*tree->cb.roffspecial)(tree->arg, tok))  
                         return(0);  
                 if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))  
                         return(0);  
                 if ( ! first)  
                         return(1);  
                 return(roffpurgepunct(tree, argv));  
         }  
   
         if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++))          if ( ! (*tree->cb.roffspecial)(tree->arg,
                                   tok, argcp, argvp, morep))
                 return(0);                  return(0);
   
         while (*argv) {          while (*argv) {
                 if (ROFF_MAX == (c = rofffindcallable(*argv))) {                  if ((*tree->cb.roffdata)(tree->arg, 1, *argv++))
                         if ( ! roffispunct(*argv)) {                          continue;
                                 if ( ! (*tree->cb.roffdata)                  return(0);
                                                 (tree->arg, 1, *argv++))          }
                                         return(0);  
                                 continue;  
                         }  
   
                         /* FIXME: this is identical to that of  
                          * roff_text. */  
   
                         /* See if only punctuation remains. */          return(1);
   }
   
                         for (j = 0; argv[j]; j++)  
                                 if ( ! roffispunct(argv[j]))  
                                         break;  
   
                         if (argv[j]) {  /* ARGSUSED */
                                 if ( ! (*tree->cb.roffdata)  static  int
                                                 (tree->arg, 0, *argv++))  roff_Ns(ROFFCALL_ARGS)
                                         return(0);  {
                                 continue;          int              j, c, first;
                         }          int              argcp[1];
           char            *argvp[1], *morep[1];
   
                         /*  Only punctuation remains. */          first = (*argv++ == tree->cur);
   
           argcp[0] = ROFF_ARGMAX;
           argvp[0] = morep[0] = NULL;
   
           if ( ! (*tree->cb.roffspecial)(tree->arg,
                                   tok, argcp, argvp, morep))
                   return(0);
   
           while (*argv) {
                   if (ROFF_MAX != (c = rofffindcallable(*argv))) {
                           if ( ! roffcall(tree, c, argv))
                                   return(0);
                         break;                          break;
                 }                  }
                 if (NULL == tokens[c].cb) {  
                         roff_err(tree, *argv, "unsupported macro `%s'",                  if ( ! roffispunct(*argv)) {
                                         toknames[c]);                          if ((*tree->cb.roffdata)(tree->arg, 1, *argv++))
                                   continue;
                         return(0);                          return(0);
                 }                  }
                 if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))                  for (j = 0; argv[j]; j++)
                           if ( ! roffispunct(argv[j]))
                                   break;
   
                   if (argv[j]) {
                           if ((*tree->cb.roffdata)(tree->arg, 0, *argv++))
                                   continue;
                         return(0);                          return(0);
                   }
   
                 break;                  break;
         }          }
   
         if ( ! first)          if ( ! first)
                 return(1);                  return(1);
   
         return(roffpurgepunct(tree, argv));          return(roffpurgepunct(tree, argv));
 }  }
   
Line 1240  roff_layout(ROFFCALL_ARGS) 
Line 1282  roff_layout(ROFFCALL_ARGS) 
                         i = 1;                          i = 1;
                         continue;                          continue;
                 }                  }
                   if ( ! roffcall(tree, c, argv))
                 if (NULL == tokens[c].cb) {  
                         roff_err(tree, *argv, "unsupported macro `%s'",  
                                         toknames[c]);  
                         return(0);                          return(0);
                 }  
   
                 if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))  
                         return(0);  
   
                 break;                  break;
         }          }
   
Line 1316  roff_text(ROFFCALL_ARGS) 
Line 1350  roff_text(ROFFCALL_ARGS) 
   
         i = 0;          i = 0;
         while (*argv) {          while (*argv) {
                 if (ROFF_MAX == (c = rofffindcallable(*argv))) {                  if (ROFF_MAX != (c = rofffindcallable(*argv))) {
                         if ( ! roffispunct(*argv)) {                          if ( ! (ROFF_LSCOPE & tokens[tok].flags))
                                 if ( ! (*tree->cb.roffdata)                                  if ( ! (*tree->cb.roffout)(tree->arg, tok))
                                                 (tree->arg, i, *argv++))  
                                         return(0);                                          return(0);
                                 i = 1;  
                                 continue;                          if ( ! roffcall(tree, c, argv))
                         }                                  return(0);
   
                         /* See if only punctuation remains. */                          if (ROFF_LSCOPE & tokens[tok].flags)
                                   if ( ! (*tree->cb.roffout)(tree->arg, tok))
                         i = 1;  
                         for (j = 0; argv[j]; j++)  
                                 if ( ! roffispunct(argv[j]))  
                                         break;  
   
                         if (argv[j]) {  
                                 if ( ! (*tree->cb.roffdata)  
                                                 (tree->arg, 0, *argv++))  
                                         return(0);                                          return(0);
                                 continue;  
                         }                          break;
                   }
   
                         /*  Only punctuation remains. */                  if ( ! roffispunct(*argv)) {
                           if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++))
                         if ( ! (*tree->cb.roffout)(tree->arg, tok))  
                                 return(0);                                  return(0);
                         break;                          i = 1;
                           continue;
                 }                  }
   
                 /*                  i = 1;
                  * A sub-command has been found.  Execute it and                  for (j = 0; argv[j]; j++)
                  * discontinue parsing for arguments.  If we're                          if ( ! roffispunct(argv[j]))
                  * line-scoped, then close out after it returns; if we                                  break;
                  * aren't, then close out before.  
                  */  
   
                 if (NULL == tokens[c].cb) {                  if (argv[j]) {
                         roff_err(tree, *argv, "unsupported macro `%s'",                          if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++))
                                         toknames[c]);  
                         return(0);  
                 }  
   
                 if ( ! (ROFF_LSCOPE & tokens[tok].flags))  
                         if ( ! (*tree->cb.roffout)(tree->arg, tok))  
                                 return(0);                                  return(0);
                           continue;
                 if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER))                  }
                         return(0);  
   
                 if (ROFF_LSCOPE & tokens[tok].flags)                  if ( ! (*tree->cb.roffout)(tree->arg, tok))
                         if ( ! (*tree->cb.roffout)(tree->arg, tok))                          return(0);
                                 return(0);  
   
                 break;                  break;
         }          }
   
Line 1429  roff_err(const struct rofftree *tree, const char *pos,
Line 1444  roff_err(const struct rofftree *tree, const char *pos,
         (*tree->cb.roffmsg)(tree->arg,          (*tree->cb.roffmsg)(tree->arg,
                         ROFF_ERROR, tree->cur, pos, buf);                          ROFF_ERROR, tree->cur, pos, buf);
 }  }
   
   
   #ifdef __linux
   /*      $OpenBSD$       */
   
   /*
    * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
    *
    * Permission to use, copy, modify, and distribute this software for any
    * purpose with or without fee is hereby granted, provided that the
    * above copyright notice and this permission notice appear in all
    * copies.
    *
    * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
    * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
    * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
    * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
    * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
    * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
    * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    * PERFORMANCE OF THIS SOFTWARE.
    */
   static size_t
   strlcat(char *dst, const char *src, size_t siz)
   {
           char *d = dst;
           const char *s = src;
           size_t n = siz;
           size_t dlen;
   
           /* Find the end of dst and adjust bytes left but don't go past
            * end */
           while (n-- != 0 && *d != '\0')
                   d++;
           dlen = d - dst;
           n = siz - dlen;
   
           if (n == 0)
                   return(dlen + strlen(s));
           while (*s != '\0') {
                   if (n != 1) {
                           *d++ = *s;
                           n--;
                   }
                   s++;
           }
           *d = '\0';
   
           return(dlen + (s - src));       /* count does not include NUL */
   }
   
   
   static size_t
   strlcpy(char *dst, const char *src, size_t siz)
   {
           char *d = dst;
           const char *s = src;
           size_t n = siz;
   
           /* Copy as many bytes as will fit */
           if (n != 0) {
                   while (--n != 0) {
                           if ((*d++ = *s++) == '\0')
                                   break;
                   }
           }
   
           /* Not enough room in dst, add NUL and traverse rest of src */
           if (n == 0) {
                   if (siz != 0)
                           *d = '\0';              /* NUL-terminate dst */
                   while (*s++)
                           ;
           }
   
           return(s - src - 1);    /* count does not include NUL */
   }
   #endif /*__linux__*/

Legend:
Removed from v.1.32  
changed lines
  Added in v.1.33

CVSweb