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

Diff for /mandoc/tbl_opts.c between version 1.2 and 1.3

version 1.2, 2010/12/28 13:47:38 version 1.3, 2010/12/29 01:16:57
Line 14 
Line 14 
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */   */
   #include <ctype.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
   
   #include "mandoc.h"
 #include "libroff.h"  #include "libroff.h"
   
 enum    tbl_ident {  enum    tbl_ident {
Line 46  struct tbl_phrase {
Line 48  struct tbl_phrase {
 /* Handle Commonwealth/American spellings. */  /* Handle Commonwealth/American spellings. */
 #define KEY_MAXKEYS      14  #define KEY_MAXKEYS      14
   
   /* Maximum length of key name string. */
   #define KEY_MAXNAME      13
   
   /* Maximum length of key number size. */
   #define KEY_MAXNUMSZ     10
   
 static  const struct tbl_phrase keys[KEY_MAXKEYS] = {  static  const struct tbl_phrase keys[KEY_MAXKEYS] = {
         { "center",      TBL_OPT_CENTRE,        KEY_CENTRE},          { "center",      TBL_OPT_CENTRE,        KEY_CENTRE},
         { "centre",      TBL_OPT_CENTRE,        KEY_CENTRE},          { "centre",      TBL_OPT_CENTRE,        KEY_CENTRE},
Line 64  static const struct tbl_phrase keys[KEY_MAXKEYS] = {
Line 72  static const struct tbl_phrase keys[KEY_MAXKEYS] = {
 };  };
   
 static  int              arg(struct tbl *, int, const char *, int *, int);  static  int              arg(struct tbl *, int, const char *, int *, int);
 static  int              opt(struct tbl *, int, const char *, int *);  static  void             opt(struct tbl *, int, const char *, int *);
   
 static int  static int
 arg(struct tbl *tbl, int ln, const char *p, int *pos, int key)  arg(struct tbl *tbl, int ln, const char *p, int *pos, int key)
 {  {
         int              sv;          int              i;
           char             buf[KEY_MAXNUMSZ];
   
 again:          while (isspace((unsigned char)p[*pos]))
         sv = *pos;                  (*pos)++;
   
         switch (tbl_next(tbl, p, pos)) {          /* Arguments always begin with a parenthesis. */
         case (TBL_TOK_OPENPAREN):  
                 break;          if ('(' != p[*pos]) {
         case (TBL_TOK_SPACE):                  TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos);
                 /* FALLTHROUGH */  
         case (TBL_TOK_TAB):  
                 goto again;  
         default:  
                 return(0);                  return(0);
         }          }
   
         sv = *pos;          (*pos)++;
   
         switch (tbl_next(tbl, p, pos)) {          /*
         case (TBL_TOK__MAX):           * The arguments can be ANY value, so we can't just stop at the
                 break;           * next close parenthesis (the argument can be a closed
         default:           * parenthesis itself).
                 return(0);           */
         }  
   
         switch (key) {          switch (key) {
         case (KEY_DELIM):          case (KEY_DELIM):
                 /* FIXME: cache this value. */                  if ('\0' == (tbl->delims[0] = p[(*pos)++])) {
                 if (2 != strlen(tbl->buf))                          TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
                         return(0);                          return(0);
                 tbl->delims[0] = tbl->buf[0];                  }
                 tbl->delims[1] = tbl->buf[1];  
                 break;                  if ('\0' == (tbl->delims[1] = p[(*pos)++])) {
         case (KEY_TAB):                          TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
                 /* FIXME: cache this value. */  
                 if (1 != strlen(tbl->buf))  
                         return(0);                          return(0);
                 tbl->tab = tbl->buf[0];                  }
                 break;                  break;
           case (KEY_TAB):
                   if ('\0' != (tbl->tab = p[(*pos)++]))
                           break;
   
                   TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
                   return(0);
         case (KEY_LINESIZE):          case (KEY_LINESIZE):
                 if ((tbl->linesize = atoi(tbl->buf)) <= 0)                  for (i = 0; i < KEY_MAXNUMSZ && p[*pos]; i++, (*pos)++) {
                         return(0);                          buf[i] = p[*pos];
                 break;                          if ( ! isdigit((unsigned char)buf[i]))
                                   break;
                   }
   
                   if (i < KEY_MAXNUMSZ) {
                           buf[i] = '\0';
                           tbl->linesize = atoi(buf);
                           break;
                   }
   
                   (*tbl->msg)(MANDOCERR_TBL, tbl->data, ln, *pos, NULL);
                   return(0);
         case (KEY_DPOINT):          case (KEY_DPOINT):
                 /* FIXME: cache this value. */                  if ('\0' != (tbl->decimal = p[(*pos)++]))
                 if (1 != strlen(tbl->buf))                          break;
                         return(0);  
                 tbl->decimal = tbl->buf[0];                  TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
                 break;                  return(0);
         default:          default:
                 abort();                  abort();
                   /* NOTREACHED */
         }          }
   
         sv = *pos;          /* End with a close parenthesis. */
   
         switch (tbl_next(tbl, p, pos)) {          if (')' == p[(*pos)++])
         case (TBL_TOK_CLOSEPAREN):                  return(1);
                 break;  
         default:  
                 return(0);  
         }  
   
         return(1);          TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos - 1);
           return(0);
 }  }
   
   static void
 static int  
 opt(struct tbl *tbl, int ln, const char *p, int *pos)  opt(struct tbl *tbl, int ln, const char *p, int *pos)
 {  {
         int              i, sv;          int              i, sv;
           char             buf[KEY_MAXNAME];
   
 again:  
         sv = *pos;  
   
         /*          /*
            * Parse individual options from the stream as surrounded by
            * this goto.  Each pass through the routine parses out a single
            * option and registers it.  Option arguments are processed in
            * the arg() function.
            */
   
   again:  /*
          * EBNF describing this section:           * EBNF describing this section:
          *           *
          * options      ::= option_list [:space:]* [;][\n]           * options      ::= option_list [:space:]* [;][\n]
Line 154  again:
Line 175  again:
          * args         ::= [:space:]* [(] [:alpha:]+ [)]           * args         ::= [:space:]* [(] [:alpha:]+ [)]
          */           */
   
         switch (tbl_next(tbl, p, pos)) {          while (isspace((unsigned char)p[*pos]))
         case (TBL_TOK__MAX):                  (*pos)++;
                 break;  
         case (TBL_TOK_SPACE):          /* Safe exit point. */
                 /* FALLTHROUGH */  
         case (TBL_TOK_TAB):          if (';' == p[*pos])
                 goto again;                  return;
         case (TBL_TOK_SEMICOLON):  
                 tbl->part = TBL_PART_LAYOUT;          /* Copy up to first non-alpha character. */
                 return(1);  
         default:          for (sv = *pos, i = 0; i < KEY_MAXNAME; i++, (*pos)++) {
                 return(0);                  buf[i] = tolower(p[*pos]);
                   if ( ! isalpha((unsigned char)buf[i]))
                           break;
         }          }
   
           /* Exit if buffer is empty (or overrun). */
   
           if (KEY_MAXNAME == i || 0 == i) {
                   TBL_MSG(tbl, MANDOCERR_TBL, ln, *pos);
                   return;
           }
   
           buf[i] = '\0';
   
           while (isspace((unsigned char)p[*pos]))
                   (*pos)++;
   
           /*
            * Look through all of the available keys to find one that
            * matches the input.  FIXME: hashtable this.
            */
   
         for (i = 0; i < KEY_MAXKEYS; i++) {          for (i = 0; i < KEY_MAXKEYS; i++) {
                 /* FIXME: hashtable this? */                  if (strcmp(buf, keys[i].name))
                 if (strcasecmp(tbl->buf, keys[i].name))  
                         continue;                          continue;
   
                   /*
                    * Note: this is more difficult to recover from, as we
                    * can be anywhere in the option sequence and it's
                    * harder to jump to the next.  Meanwhile, just bail out
                    * of the sequence altogether.
                    */
   
                 if (keys[i].key)                  if (keys[i].key)
                         tbl->opts |= keys[i].key;                          tbl->opts |= keys[i].key;
                 else if ( ! arg(tbl, ln, p, pos, keys[i].ident))                  else if ( ! arg(tbl, ln, p, pos, keys[i].ident))
                         return(0);                          return;
   
                 break;                  break;
         }          }
   
           /*
            * Allow us to recover from bad options by continuing to another
            * parse sequence.
            */
   
         if (KEY_MAXKEYS == i)          if (KEY_MAXKEYS == i)
                 return(0);                  TBL_MSG(tbl, MANDOCERR_TBLOPT, ln, sv);
   
         return(opt(tbl, ln, p, pos));          /* Try again... */
   
           goto again;
 }  }
   
 int  int
Line 191  tbl_option(struct tbl *tbl, int ln, const char *p)
Line 245  tbl_option(struct tbl *tbl, int ln, const char *p)
 {  {
         int              pos;          int              pos;
   
           /*
            * Table options are always on just one line, so automatically
            * switch into the next input mode here.
            */
           tbl->part = TBL_PART_LAYOUT;
   
         pos = 0;          pos = 0;
         return(opt(tbl, ln, p, &pos));          opt(tbl, ln, p, &pos);
   
           /* Always succeed. */
           return(1);
 }  }

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

CVSweb