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

Diff for /texi2mdoc/util.c between version 1.29 and 1.34

version 1.29, 2015/03/07 11:53:21 version 1.34, 2015/03/19 09:53:36
Line 103  texivaluefree(struct texivalue *p)
Line 103  texivaluefree(struct texivalue *p)
         free(p->value);          free(p->value);
 }  }
   
   static void
   texidex_free(struct texidex *p)
   {
           size_t   i;
   
           for (i = 0; i < p->indexsz; i++)
                   free(p->index[i].term);
   
           free(p->index);
           free(p->name);
           p->index = NULL;
           p->indexsz = 0;
   }
   
 /*  /*
    * Add the text beginning at "index" and of "sz" bytes to the index
    * named "tok" with name size "toksz".
    * This will also output the necessary mdoc(7) to construct the index.
    */
   void
   texindex(struct texi *p, const char *tok,
           size_t toksz, const char *index, size_t sz)
   {
           size_t   i, isz;
   #ifdef HAVE_INDEX
           char    *cp;
   #endif
   
           if (0 == sz) {
                   texiwarn(p, "zero-length index entry");
                   return;
           }
   
           /* Look for the index.  (Must be found.) */
           for (i = 0; i < p->indexsz; i++) {
                   if (strlen(p->indexs[i].name) != toksz)
                           continue;
                   if (strncmp(p->indexs[i].name, tok, toksz))
                           continue;
                   break;
           }
   
           assert(i < p->indexsz);
           isz = p->indexs[i].indexsz;
           /* Reallocate index's terms. */
           p->indexs[i].index = realloc
                   (p->indexs[i].index,
                    (isz + 1) * sizeof(struct texiterm));
           if (NULL == p->indexs[i].index)
                   texiabort(p, NULL);
   
           /* Add term to term array. */
           p->indexs[i].index[isz].chapter = p->nodecur;
           p->indexs[i].index[isz].term = malloc(sz + 1);
           if (NULL == p->indexs[i].index[isz].term)
                   texiabort(p, NULL);
           memcpy(p->indexs[i].index[isz].term, index, sz);
           p->indexs[i].index[isz].term[sz] = '\0';
   
           /* Output mdoc(7) for index. */
   #ifdef HAVE_INDEX
           p->seenvs = -1;
           teximacroopen(p, "Ix");
           texiputchars(p, "idx");
           texiputchars(p, p->indexs[i].name);
           cp = p->indexs[i].index[isz].term;
           while ('\n' != *cp)
                   texiputchar(p, *cp++);
           teximacroclose(p);
   #endif
           p->indexs[i].indexsz++;
   }
   
   /*
    * Add an index entry named "tok" of length "sz".
    * This usually consists of two letters, e.g., "cp" or "vr".
    * This does nothing if the index exists or is zero-sized.
    */
   void
   texindex_add(struct texi *p, const char *tok, size_t sz)
   {
           size_t   i;
           char    *cp;
   
           if (0 == sz)
                   return;
   
           /* Make sure we don't have a duplicate. */
           for (i = 0; i < p->indexsz; i++) {
                   if (strlen(p->indexs[i].name) != sz)
                           continue;
                   if (strncmp(p->indexs[i].name, tok, sz))
                           continue;
                   return;
           }
   
           /* Reallocate indices. */
           p->indexs = realloc(p->indexs,
                   sizeof(struct texidex) *
                   (p->indexsz + 1));
           if (NULL == p->indexs)
                   texiabort(p, NULL);
           if (NULL == (cp = malloc(sz + 1)))
                   texiabort(p, NULL);
           memcpy(cp, tok, sz);
           cp[sz] = '\0';
           p->indexs[p->indexsz].name = cp;
           p->indexs[p->indexsz].index = NULL;
           p->indexs[p->indexsz].indexsz = 0;
           p->indexsz++;
   }
   
   /*
  * Unmap all files that we're currently using and free all resources   * Unmap all files that we're currently using and free all resources
  * that we've allocated during the parse.   * that we've allocated during the parse.
  * The utility should exit(...) after this is called.   * The utility should exit(...) after this is called.
Line 128  texiexit(struct texi *p)
Line 240  texiexit(struct texi *p)
         for (i = 0; i < p->dirsz; i++)          for (i = 0; i < p->dirsz; i++)
                 free(p->dirs[i]);                  free(p->dirs[i]);
         for (i = 0; i < p->indexsz; i++)          for (i = 0; i < p->indexsz; i++)
                 free(p->indexs[i]);                  texidex_free(&p->indexs[i]);
         for (i = 0; i < p->valsz; i++)          for (i = 0; i < p->valsz; i++)
                 texivaluefree(&p->vals[i]);                  texivaluefree(&p->vals[i]);
   
           free(p->nodecache);
         free(p->macros);          free(p->macros);
         free(p->vals);          free(p->vals);
         free(p->indexs);          free(p->indexs);
Line 161  texiabort(struct texi *p, const char *errstring)
Line 274  texiabort(struct texi *p, const char *errstring)
 void  void
 texiwarn(const struct texi *p, const char *fmt, ...)  texiwarn(const struct texi *p, const char *fmt, ...)
 {  {
         va_list                  ap;          va_list                  ap;
         const struct texifile   *f;          const struct texifile   *f;
   
         f = &p->files[p->filepos - 1];          f = &p->files[p->filepos - 1];
   
         if (f->insplice)          if (f->insplice)
                 fprintf(stderr, "%s:%zu:%zu (%zuB left in splice): "                  fprintf(stderr, "%s:%zu:%zu (%zuB left in splice): "
                         "warning: ", f->name, f->line + 1,                          "warning: ", f->name, f->line + 1,
                         f->col + 1, f->insplice);                          f->col + 1, f->insplice);
         else          else
                 fprintf(stderr, "%s:%zu:%zu: warning: ",                  fprintf(stderr, "%s:%zu:%zu: warning: ",
Line 187  texiwarn(const struct texi *p, const char *fmt, ...)
Line 300  texiwarn(const struct texi *p, const char *fmt, ...)
 void  void
 texierr(struct texi *p, const char *fmt, ...)  texierr(struct texi *p, const char *fmt, ...)
 {  {
         va_list          ap;          va_list          ap;
         struct texifile *f;          struct texifile *f;
   
         f = &p->files[p->filepos - 1];          f = &p->files[p->filepos - 1];
   
         if (f->insplice)          if (f->insplice)
                 fprintf(stderr, "%s:%zu:%zu: (%zuB left in splice): "                  fprintf(stderr, "%s:%zu:%zu: (%zuB left in splice): "
                         "error: ", f->name, f->line + 1,                          "error: ", f->name, f->line + 1,
                         f->col + 1, f->insplice);                          f->col + 1, f->insplice);
         else          else
                 fprintf(stderr, "%s:%zu:%zu: error: ",                  fprintf(stderr, "%s:%zu:%zu: error: ",
Line 251  texiputchars(struct texi *p, const char *s)
Line 364  texiputchars(struct texi *p, const char *s)
                 fputs("\\&", p->outfile);                  fputs("\\&", p->outfile);
         if ('\'' == *s && 0 == p->outcol)          if ('\'' == *s && 0 == p->outcol)
                 fputs("\\&", p->outfile);                  fputs("\\&", p->outfile);
         if (p->uppercase)          if (p->uppercase)
                 for ( ; '\0' != *s; s++)                  for ( ; '\0' != *s; s++)
                         p->outcol += fputc(toupper                          p->outcol += fputc(toupper
                                 ((unsigned int)*s), p->outfile);                                  ((unsigned int)*s), p->outfile);
Line 280  void
Line 393  void
 teximacroclose(struct texi *p)  teximacroclose(struct texi *p)
 {  {
   
         if (p->ign)          if (p->ign || p->literal|| TEXILIST_TABLE == p->list)
                 return;                  return;
   
         if (0 == --p->outmacro) {          if (0 == --p->outmacro) {
                 fputc('\n', p->outfile);                  fputc('\n', p->outfile);
                 p->outcol = p->seenws = 0;                  p->outcol = p->seenws = 0;
         }          }
         p->seenvs = 0;  
 }  }
   
 /*  /*
Line 301  teximacroopen(struct texi *p, const char *s)
Line 413  teximacroopen(struct texi *p, const char *s)
 {  {
         int      rc;          int      rc;
   
         if (p->ign)          if (p->ign || p->literal|| TEXILIST_TABLE == p->list)
                 return;                  return;
   
         if (p->outcol && 0 == p->outmacro) {          if (p->outcol && 0 == p->outmacro) {
Line 309  teximacroopen(struct texi *p, const char *s)
Line 421  teximacroopen(struct texi *p, const char *s)
                 p->outcol = 0;                  p->outcol = 0;
         }          }
   
           if (p->seenvs > 0 && 0 == p->outmacro)
                   fputs(".Pp\n", p->outfile);
   
         if (0 == p->outmacro)          if (0 == p->outmacro)
                 fputc('.', p->outfile);                  fputc('.', p->outfile);
         else          else
Line 320  teximacroopen(struct texi *p, const char *s)
Line 435  teximacroopen(struct texi *p, const char *s)
         fputc(' ', p->outfile);          fputc(' ', p->outfile);
         p->outcol++;          p->outcol++;
         p->outmacro++;          p->outmacro++;
         p->seenws = 0;          p->seenws = p->seenvs = 0;
         p->seenvs = 0;  
 }  }
   
 /*  /*
Line 338  teximacro(struct texi *p, const char *s)
Line 452  teximacro(struct texi *p, const char *s)
                 texierr(p, "\"%s\" in open line scope!?", s);                  texierr(p, "\"%s\" in open line scope!?", s);
         if (p->literal)          if (p->literal)
                 texierr(p, "\"%s\" in a literal scope!?", s);                  texierr(p, "\"%s\" in a literal scope!?", s);
   
         if (p->outcol)          if (p->outcol)
                 fputc('\n', p->outfile);                  fputc('\n', p->outfile);
           if (p->seenvs > 0)
                   fputs(".Pp\n", p->outfile);
   
         fputc('.', p->outfile);          fputc('.', p->outfile);
         fputs(s, p->outfile);          fputs(s, p->outfile);
         fputc('\n', p->outfile);          fputc('\n', p->outfile);
         p->outcol = p->seenws = 0;          p->outcol = p->seenws = 0;
         p->seenvs = 0;  
 }  }
   
 /*  /*
Line 356  void
Line 470  void
 texivspace(struct texi *p)  texivspace(struct texi *p)
 {  {
   
         if (TEXILIST_TABLE != p->list)          if (TEXILIST_TABLE != p->list && p->seenvs >= 0)
                 teximacro(p, "Pp");                  p->seenvs = 1;
 }  }
   
 /*  /*
Line 419  texipunctuate(struct texi *p, size_t *pos)
Line 533  texipunctuate(struct texi *p, size_t *pos)
         }          }
         if (end == *pos)          if (end == *pos)
                 return;                  return;
         if (end + 1 == BUFSZ(p) || ' ' == BUF(p)[end] ||          if (end + 1 == BUFSZ(p) || ' ' == BUF(p)[end] ||
                 '\n' == BUF(p)[end]) {                  '@' == BUF(p)[end] || '\n' == BUF(p)[end]) {
                 for ( ; start < end; start++) {                  for ( ; start < end; start++) {
                         texiputchar(p, ' ');                          texiputchar(p, ' ');
                         texiputchar(p, BUF(p)[start]);                          texiputchar(p, BUF(p)[start]);
Line 437  texipunctuate(struct texi *p, size_t *pos)
Line 551  texipunctuate(struct texi *p, size_t *pos)
 static size_t  static size_t
 advancenext(struct texi *p, size_t *pos)  advancenext(struct texi *p, size_t *pos)
 {  {
   
         if (p->literal) {          if (p->literal) {
                 while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) {                  while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) {
                         texiputchar(p, BUF(p)[*pos]);                          texiputchar(p, BUF(p)[*pos]);
                         advance(p, pos);                          advance(p, pos);
                 }                  }
                 return(*pos);                  return(*pos);
         }          }
   
         while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) {          while (*pos < BUFSZ(p) && ismspace(BUF(p)[*pos])) {
                 p->seenws = 1;                  p->seenws = 1;
                   if (0 == p->seenvs && '\n' == BUF(p)[*pos])
                           if (*pos + 1 < BUFSZ(p) && '\n' == BUF(p)[*pos + 1])
                                   p->seenvs = 1;
                 advance(p, pos);                  advance(p, pos);
         }          }
         return(*pos);          return(*pos);
Line 465  advanceeoln(struct texi *p, size_t *pos, int consumenl
Line 582  advanceeoln(struct texi *p, size_t *pos, int consumenl
         while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) {          while (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos]) {
                 if ('@' == BUF(p)[*pos])                  if ('@' == BUF(p)[*pos])
                         advance(p, pos);                          advance(p, pos);
                 advance(p, pos);                  if (*pos < BUFSZ(p))
                           advance(p, pos);
         }          }
         if (*pos < BUFSZ(p) && consumenl)          if (*pos < BUFSZ(p) && consumenl)
                 advance(p, pos);                  advance(p, pos);
Line 481  advanceto(struct texi *p, size_t *pos, size_t end)
Line 599  advanceto(struct texi *p, size_t *pos, size_t end)
 {  {
   
         assert(*pos <= end);          assert(*pos <= end);
         while (*pos < end)          while (*pos < end)
                 advance(p, pos);                  advance(p, pos);
 }  }
   
 static void  static void
 texiexecmacro(struct texi *p, struct teximacro *m, size_t sv, size_t *pos)  texiexecmacro(struct texi *p, struct teximacro *m, size_t sv, size_t *pos)
 {  {
         size_t            valsz, realsz, aasz, asz,          size_t            valsz, realsz, aasz, asz,
                            ssz, i, j, k, start, end;                             ssz, i, j, k, start, end;
         char             *val;          char             *val;
         char            **args;          char            **args;
Line 546  texiexecmacro(struct texi *p, struct teximacro *m, siz
Line 664  texiexecmacro(struct texi *p, struct teximacro *m, siz
   
                 /* Parse to terminating delimiter. */                  /* Parse to terminating delimiter. */
                 /* FIXME: embedded, escaped delimiters? */                  /* FIXME: embedded, escaped delimiters? */
                 for (start = end = i + 1; end < realsz; end++)                  for (start = end = i + 1; end < realsz; end++)
                         if ('\\' == m->value[end])                          if ('\\' == m->value[end])
                                 break;                                  break;
                 if (end == realsz)                  if (end == realsz)
Line 560  texiexecmacro(struct texi *p, struct teximacro *m, siz
Line 678  texiexecmacro(struct texi *p, struct teximacro *m, siz
                         break;                          break;
                 }                  }
   
                 /*                  /*
                  * Argument didn't exist in argument table.                   * Argument didn't exist in argument table.
                  * Just ignore it.                   * Just ignore it.
                  */                   */
                 if (k == aasz) {                  if (k == aasz) {
Line 576  texiexecmacro(struct texi *p, struct teximacro *m, siz
Line 694  texiexecmacro(struct texi *p, struct teximacro *m, siz
                                 texiabort(p, NULL);                                  texiabort(p, NULL);
                 }                  }
   
                 for (cp = args[k]; '\0' != *cp; cp++)                  for (cp = args[k]; '\0' != *cp; cp++)
                         val[j++] = *cp;                          val[j++] = *cp;
   
                 val[j] = '\0';                  val[j] = '\0';
Line 589  texiexecmacro(struct texi *p, struct teximacro *m, siz
Line 707  texiexecmacro(struct texi *p, struct teximacro *m, siz
                 free(args[i]);                  free(args[i]);
         free(args);          free(args);
         free(val);          free(val);
 }  }
   
 /*  /*
  * Output a free-form word in the input stream, progressing to the next   * Output a free-form word in the input stream, progressing to the next
Line 599  texiexecmacro(struct texi *p, struct teximacro *m, siz
Line 717  texiexecmacro(struct texi *p, struct teximacro *m, siz
 static void  static void
 parseword(struct texi *p, size_t *pos, char extra)  parseword(struct texi *p, size_t *pos, char extra)
 {  {
         size_t           i, end, len;          size_t           i, end, len;
         int              c;          int              c;
   
         /*          /*
          * If a prior word had a terminating double-newline, then begin           * If a prior word had a terminating double-newline, then begin
Line 608  parseword(struct texi *p, size_t *pos, char extra)
Line 726  parseword(struct texi *p, size_t *pos, char extra)
          * We don't do this if we're in a literal context (we'll print           * We don't do this if we're in a literal context (we'll print
          * out the newlines themselves) nor in a `TS' table.           * out the newlines themselves) nor in a `TS' table.
          */           */
         if (p->seenvs && 0 == p->literal && TEXILIST_TABLE != p->list)          if (p->seenvs > 0 && 0 == p->literal && TEXILIST_TABLE != p->list) {
                 teximacro(p, "Pp");                  if (p->outcol > 0)
                           fputc('\n', p->outfile);
                   fputs(".Pp\n", p->outfile);
                   p->outcol = 0;
           }
   
         p->seenvs = 0;  
   
         /*          /*
          * Some line control: if we (non-macro, non-literal) already           * Some line control: if we (non-macro, non-literal) already
          * have more than 72 characters written to the screen, then           * have more than 72 characters written to the screen, then
          * output a newline before getting started.           * output a newline before getting started.
          */           */
         if (p->seenws && 0 == p->outmacro &&          if (p->seenws && 0 == p->outmacro &&
                  p->outcol > 72 && 0 == p->literal)                   p->outcol > 72 && 0 == p->literal)
                 texiputchar(p, '\n');                  texiputchar(p, '\n');
   
Line 684  parseword(struct texi *p, size_t *pos, char extra)
Line 804  parseword(struct texi *p, size_t *pos, char extra)
                         continue;                          continue;
                 }                  }
   
                 if (*pos < BUFSZ(p) - 2 &&                  if ('"' == BUF(p)[*pos]) {
                          '-' == BUF(p)[*pos] &&                          texiputchars(p, "\\(dq");
                          '-' == BUF(p)[*pos + 1] &&                  } else if (*pos < BUFSZ(p) - 2 &&
                            '-' == BUF(p)[*pos] &&
                            '-' == BUF(p)[*pos + 1] &&
                          '-' == BUF(p)[*pos + 2]) {                           '-' == BUF(p)[*pos + 2]) {
                         texiputchars(p, "\\(em");                          texiputchars(p, "\\(em");
                         advance(p, pos);                          advance(p, pos);
                         advance(p, pos);                          advance(p, pos);
                 } else if (*pos < BUFSZ(p) - 1 &&                  } else if (*pos < BUFSZ(p) - 1 &&
                          '-' == BUF(p)[*pos] &&                           '-' == BUF(p)[*pos] &&
                          '-' == BUF(p)[*pos + 1]) {                           '-' == BUF(p)[*pos + 1]) {
                         texiputchars(p, "\\(en");                          texiputchars(p, "\\(en");
                         advance(p, pos);                          advance(p, pos);
                 } else if (*pos < BUFSZ(p) - 1 &&                  } else if (*pos < BUFSZ(p) - 1 &&
                          '`' == BUF(p)[*pos] &&                           '`' == BUF(p)[*pos] &&
                          '`' == BUF(p)[*pos + 1]) {                           '`' == BUF(p)[*pos + 1]) {
                         texiputchars(p, "\\(lq");                          texiputchars(p, "\\(lq");
                         advance(p, pos);                          advance(p, pos);
                 } else if (*pos < BUFSZ(p) - 1 &&                  } else if (*pos < BUFSZ(p) - 1 &&
                          '\'' == BUF(p)[*pos] &&                           '\'' == BUF(p)[*pos] &&
                          '\'' == BUF(p)[*pos + 1]) {                           '\'' == BUF(p)[*pos + 1]) {
                         texiputchars(p, "\\(rq");                          texiputchars(p, "\\(rq");
                         advance(p, pos);                          advance(p, pos);
Line 712  parseword(struct texi *p, size_t *pos, char extra)
Line 834  parseword(struct texi *p, size_t *pos, char extra)
                 advance(p, pos);                  advance(p, pos);
         }          }
   
         if (*pos + 1 < BUFSZ(p) &&          /*
                 '\n' == BUF(p)[*pos] &&  
                 '\n' == BUF(p)[*pos + 1])  
                 p->seenvs = 1;  
   
         /*  
          * New sentence, new line:if we (non-macro, non-literal) see a           * New sentence, new line:if we (non-macro, non-literal) see a
          * period at the end of the last printed word, then open a           * period at the end of the last printed word, then open a
          * newline.           * newline.
          */           */
         if (0 == p->literal && 0 == p->outmacro &&          if (0 == p->literal && 0 == p->outmacro && *pos < BUFSZ(p))
                 *pos < BUFSZ(p) && '.' == BUF(p)[*pos - 1])                  switch (BUF(p)[*pos - 1]) {
                 texiputchar(p, '\n');                  case ('.'):
                   case ('!'):
                   case ('?'):
                           texiputchar(p, '\n');
                           break;
                   default:
                           break;
                   }
   
           p->seenvs = 0;
 }  }
   
 /*  /*
Line 763  texicmd(const struct texi *p, size_t pos, size_t *end,
Line 889  texicmd(const struct texi *p, size_t pos, size_t *end,
   
         /* Scan to the end of the possible command name. */          /* Scan to the end of the possible command name. */
         for (*end = pos; *end < BUFSZ(p) && ! ismspace(BUF(p)[*end]); (*end)++)          for (*end = pos; *end < BUFSZ(p) && ! ismspace(BUF(p)[*end]); (*end)++)
                 if ((*end > pos && ('@' == BUF(p)[*end] ||                  if ((*end > pos && ('@' == BUF(p)[*end] ||
                           '{' == BUF(p)[*end] || '}' == BUF(p)[*end])))                            '{' == BUF(p)[*end] || '}' == BUF(p)[*end])))
                         break;                          break;
   
Line 778  texicmd(const struct texi *p, size_t pos, size_t *end,
Line 904  texicmd(const struct texi *p, size_t pos, size_t *end,
   
         /* Look for it in our indices. */          /* Look for it in our indices. */
         for (i = 0; i < p->indexsz; i++) {          for (i = 0; i < p->indexsz; i++) {
                 toksz = strlen(p->indexs[i]);                  toksz = strlen(p->indexs[i].name);
                 if (len != 5 + toksz)                  if (len != 5 + toksz)
                         continue;                          continue;
                 if (strncmp(&BUF(p)[pos], p->indexs[i], toksz))                  if (strncmp(&BUF(p)[pos], p->indexs[i].name, toksz))
                         continue;                          continue;
                 if (0 == strncmp(&BUF(p)[pos + toksz], "index", 5))                  if (0 == strncmp(&BUF(p)[pos + toksz], "index", 5))
                         return(TEXICMD_USER_INDEX);                          return(TEXICMD_USER_INDEX);
Line 848  parsearg(struct texi *p, size_t *pos, size_t num)
Line 974  parsearg(struct texi *p, size_t *pos, size_t num)
                 advanceto(p, pos, end);                  advanceto(p, pos, end);
                 if (NULL != macro)                  if (NULL != macro)
                         texiexecmacro(p, macro, sv, pos);                          texiexecmacro(p, macro, sv, pos);
                 if (TEXICMD__MAX == cmd)                  if (TEXICMD__MAX == cmd)
                         continue;                          continue;
                 if (NULL != texitoks[cmd].fp)                  if (NULL != texitoks[cmd].fp)
                         (*texitoks[cmd].fp)(p, cmd, pos);                          (*texitoks[cmd].fp)(p, cmd, pos);
Line 909  parsebracket(struct texi *p, size_t *pos, int dostack)
Line 1035  parsebracket(struct texi *p, size_t *pos, int dostack)
                 advanceto(p, pos, end);                  advanceto(p, pos, end);
                 if (NULL != macro)                  if (NULL != macro)
                         texiexecmacro(p, macro, sv, pos);                          texiexecmacro(p, macro, sv, pos);
                 if (TEXICMD__MAX == cmd)                  if (TEXICMD__MAX == cmd)
                         continue;                          continue;
                 if (NULL != texitoks[cmd].fp)                  if (NULL != texitoks[cmd].fp)
                         (*texitoks[cmd].fp)(p, cmd, pos);                          (*texitoks[cmd].fp)(p, cmd, pos);
Line 935  parseeoln(struct texi *p, size_t *pos)
Line 1061  parseeoln(struct texi *p, size_t *pos)
                                 texiputchar(p, BUF(p)[*pos]);                                  texiputchar(p, BUF(p)[*pos]);
                         advance(p, pos);                          advance(p, pos);
                 }                  }
                   if (*pos == BUFSZ(p)) {
                           texiwarn(p, "unexpected EOF");
                           return;
                   }
                 switch (BUF(p)[*pos]) {                  switch (BUF(p)[*pos]) {
                 case ('}'):                  case ('}'):
                         if (0 == p->ign)                          if (0 == p->ign)
Line 946  parseeoln(struct texi *p, size_t *pos)
Line 1076  parseeoln(struct texi *p, size_t *pos)
                                 texiwarn(p, "unexpected \"{\"");                                  texiwarn(p, "unexpected \"{\"");
                         advance(p, pos);                          advance(p, pos);
                         continue;                          continue;
                   case ('\n'):
                           continue;
                 case ('@'):                  case ('@'):
                         break;                          break;
                 default:                  default:
Line 958  parseeoln(struct texi *p, size_t *pos)
Line 1090  parseeoln(struct texi *p, size_t *pos)
                 advanceto(p, pos, end);                  advanceto(p, pos, end);
                 if (NULL != macro)                  if (NULL != macro)
                         texiexecmacro(p, macro, sv, pos);                          texiexecmacro(p, macro, sv, pos);
                 if (TEXICMD__MAX == cmd)                  if (TEXICMD__MAX == cmd)
                         continue;                          continue;
                 if (NULL != texitoks[cmd].fp)                  if (NULL != texitoks[cmd].fp)
                         (*texitoks[cmd].fp)(p, cmd, pos);                          (*texitoks[cmd].fp)(p, cmd, pos);
Line 968  parseeoln(struct texi *p, size_t *pos)
Line 1100  parseeoln(struct texi *p, size_t *pos)
                 advance(p, pos);                  advance(p, pos);
 }  }
   
   enum texicmd
   peeklinecmd(const struct texi *p, size_t pos)
   {
           size_t          end;
   
           while (pos < BUFSZ(p) && isws(BUF(p)[pos]))
                   pos++;
           if (pos == BUFSZ(p) || '@' != BUF(p)[pos])
                   return(TEXICMD__MAX);
           return(texicmd(p, pos, &end, NULL));
   }
   
 /*  /*
  * Peek to see if there's a command after subsequent whitespace.   * Peek to see if there's a command after subsequent whitespace.
  * If so, return the macro identifier.   * If so, return the macro identifier.
Line 989  peekcmd(const struct texi *p, size_t pos)
Line 1133  peekcmd(const struct texi *p, size_t pos)
  * Parse a single word or command.   * Parse a single word or command.
  * This will return immediately at the EOF.   * This will return immediately at the EOF.
  */   */
 static void  void
 parsesingle(struct texi *p, size_t *pos)  parsesingle(struct texi *p, size_t *pos)
 {  {
         size_t            end, sv;          size_t            end, sv;
Line 1022  parsesingle(struct texi *p, size_t *pos)
Line 1166  parsesingle(struct texi *p, size_t *pos)
         advanceto(p, pos, end);          advanceto(p, pos, end);
         if (NULL != macro)          if (NULL != macro)
                 texiexecmacro(p, macro, sv, pos);                  texiexecmacro(p, macro, sv, pos);
         if (TEXICMD__MAX == cmd)          if (TEXICMD__MAX == cmd)
                 return;                  return;
         if (NULL != texitoks[cmd].fp)          if (NULL != texitoks[cmd].fp)
                 (*texitoks[cmd].fp)(p, cmd, pos);                  (*texitoks[cmd].fp)(p, cmd, pos);
Line 1063  parseeof(struct texi *p)
Line 1207  parseeof(struct texi *p)
 {  {
         size_t   pos;          size_t   pos;
   
         for (pos = 0; pos < BUFSZ(p); )          for (pos = 0; pos < BUFSZ(p); )
                 parsesingle(p, &pos);                  parsesingle(p, &pos);
 }  }
   
Line 1105  parseto(struct texi *p, size_t *pos, const char *endto
Line 1249  parseto(struct texi *p, size_t *pos, const char *endto
   
         endtoksz = strlen(endtoken);          endtoksz = strlen(endtoken);
         assert(endtoksz > 0);          assert(endtoksz > 0);
   
         while ((*pos = advancenext(p, pos)) < BUFSZ(p)) {          while ((*pos = advancenext(p, pos)) < BUFSZ(p)) {
                 switch (BUF(p)[*pos]) {                  switch (BUF(p)[*pos]) {
                 case ('}'):                  case ('}'):
Line 1131  parseto(struct texi *p, size_t *pos, const char *endto
Line 1275  parseto(struct texi *p, size_t *pos, const char *endto
                 if (TEXICMD_END == cmd) {                  if (TEXICMD_END == cmd) {
                         while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))                          while (*pos < BUFSZ(p) && isws(BUF(p)[*pos]))
                                 advance(p, pos);                                  advance(p, pos);
                         /*                          /*
                          * FIXME: check the full word, not just its                           * FIXME: check the full word, not just its
                          * initial substring!                           * initial substring!
                          */                           */
Line 1144  parseto(struct texi *p, size_t *pos, const char *endto
Line 1288  parseto(struct texi *p, size_t *pos, const char *endto
                                 texiwarn(p, "unexpected \"end\"");                                  texiwarn(p, "unexpected \"end\"");
                         advanceeoln(p, pos, 0);                          advanceeoln(p, pos, 0);
                         continue;                          continue;
                 }                  }
                 if (NULL != macro)                  if (NULL != macro)
                         texiexecmacro(p, macro, sv, pos);                          texiexecmacro(p, macro, sv, pos);
                 if (TEXICMD__MAX == cmd)                  if (TEXICMD__MAX == cmd)
                         continue;                          continue;
                 if (NULL != texitoks[cmd].fp)                  if (NULL != texitoks[cmd].fp)
                         (*texitoks[cmd].fp)(p, cmd, pos);                          (*texitoks[cmd].fp)(p, cmd, pos);
         }          }
   
           if (*pos == BUFSZ(p))
                   texiwarn(p, "EOF expecting \"%s\" end\n", endtoken);
 }  }
   
 /*  /*
Line 1175  parsestdin(struct texi *p)
Line 1322  parsestdin(struct texi *p)
                 if (f->mapsz == f->mapmaxsz) {                  if (f->mapsz == f->mapmaxsz) {
                         if (f->mapmaxsz == (1U << 31))                          if (f->mapmaxsz == (1U << 31))
                                 texierr(p, "stdin buffer too long");                                  texierr(p, "stdin buffer too long");
                         f->mapmaxsz = f->mapmaxsz > 65536 / 2 ?                          f->mapmaxsz = f->mapmaxsz > 65536 / 2 ?
                                 2 * f->mapmaxsz : 65536;                                  2 * f->mapmaxsz : 65536;
                         f->map = realloc(f->map, f->mapmaxsz);                          f->map = realloc(f->map, f->mapmaxsz);
                         if (NULL == f->map)                          if (NULL == f->map)
                                 texiabort(p, NULL);                                  texiabort(p, NULL);
                 }                  }
                 ssz = read(STDIN_FILENO, f->map +                  ssz = read(STDIN_FILENO, f->map +
                         (int)f->mapsz, f->mapmaxsz - f->mapsz);                          (int)f->mapsz, f->mapmaxsz - f->mapsz);
                 if (0 == ssz)                  if (0 == ssz)
                         break;                          break;
                 else if (-1 == ssz)                  else if (-1 == ssz)
                         texiabort(p, NULL);                          texiabort(p, NULL);
         }          }
   
Line 1209  parsefile(struct texi *p, const char *fname, int parse
Line 1356  parsefile(struct texi *p, const char *fname, int parse
         size_t           i;          size_t           i;
         char            *map;          char            *map;
   
         if (64 == p->filepos)          if (64 == p->filepos)
                 texierr(p, "too many open files");                  texierr(p, "too many open files");
         f = &p->files[p->filepos];          f = &p->files[p->filepos];
         memset(f, 0, sizeof(struct texifile));          memset(f, 0, sizeof(struct texifile));
Line 1221  parsefile(struct texi *p, const char *fname, int parse
Line 1368  parsefile(struct texi *p, const char *fname, int parse
         } else if (-1 == fstat(fd, &st)) {          } else if (-1 == fstat(fd, &st)) {
                 close(fd);                  close(fd);
                 texiabort(p, fname);                  texiabort(p, fname);
         }          }
   
         f->mapsz = f->mapmaxsz = st.st_size;          f->mapsz = f->mapmaxsz = st.st_size;
         map = mmap(NULL, f->mapsz,          map = mmap(NULL, f->mapsz,
Line 1371  valueadd(struct texi *p, char *key, char *val)
Line 1518  valueadd(struct texi *p, char *key, char *val)
                 p->vals[i].value = val;                  p->vals[i].value = val;
         } else {          } else {
                 /* FIXME: reallocarray() */                  /* FIXME: reallocarray() */
                 p->vals = realloc(p->vals,                  p->vals = realloc(p->vals,
                         (p->valsz + 1) *                          (p->valsz + 1) *
                          sizeof(struct texivalue));                           sizeof(struct texivalue));
                 if (NULL == p->vals)                  if (NULL == p->vals)
Line 1442  argparse(struct texi *p, size_t *pos, size_t *argsz, s
Line 1589  argparse(struct texi *p, size_t *pos, size_t *argsz, s
                 start = *pos;                  start = *pos;
                 stack = 0;                  stack = 0;
                 while (*pos < BUFSZ(p)) {                  while (*pos < BUFSZ(p)) {
                         /*                          /*
                          * According to the manual, commas within                           * According to the manual, commas within
                          * embedded commands are escaped.                           * embedded commands are escaped.
                          * We keep track of embedded-ness in the "stack"                           * We keep track of embedded-ness in the "stack"
Line 1484  argparse(struct texi *p, size_t *pos, size_t *argsz, s
Line 1631  argparse(struct texi *p, size_t *pos, size_t *argsz, s
                 advance(p, pos);                  advance(p, pos);
         }          }
   
         if (*pos == BUFSZ(p))          if (*pos == BUFSZ(p))
                 texierr(p, "unterminated arguments");                  texierr(p, "unterminated arguments");
         assert('}' == BUF(p)[*pos]);          assert('}' == BUF(p)[*pos]);
         advance(p, pos);          advance(p, pos);
Line 1503  teximdocclose(struct texi *p, int last)
Line 1650  teximdocclose(struct texi *p, int last)
 {  {
         char     buf[PATH_MAX];          char     buf[PATH_MAX];
   
         if (NULL == p->chapters || 0 == p->chapnum)          if (NULL == p->chapters || 1 == p->nodesz)
                 return;                  return;
   
         teximacro(p, "Sh INFO NAVIGATION");          teximacro(p, "Sh INFO NAVIGATION");
   
         /* Print a reference to the "top" node. */          /* Print a reference to the "top" node. */
         if (p->chapnum > 1) {          if (-1 != p->nodecache[p->nodecur].up) {
                 texiputchars(p, "Top node,");                  texiputchars(p, "Top node,");
                 snprintf(buf, sizeof(buf), "node1 7");                  snprintf(buf, sizeof(buf), "%s-%zd 7",
                           p->chapters, p->nodecache[p->nodecur].up);
                   p->seenvs = 0;
                 teximacroopen(p, "Xr ");                  teximacroopen(p, "Xr ");
                 texiputchars(p, buf);                  texiputchars(p, buf);
                 texiputchars(p, " ;");                  texiputchars(p, " ;");
                 teximacroclose(p);                  teximacroclose(p);
         }          }
   
         /* Print a reference to the previous node. */          if (-1 != p->nodecache[p->nodecur].prev) {
         if (p->chapnum > 2) {  
                 texiputchars(p, "previous node,");                  texiputchars(p, "previous node,");
                 snprintf(buf, sizeof(buf),                  snprintf(buf, sizeof(buf), "%s-%zd 7",
                         "node%zu 7", p->chapnum - 1);                          p->chapters, p->nodecache[p->nodecur].prev);
                   p->seenvs = 0;
                 teximacroopen(p, "Xr ");                  teximacroopen(p, "Xr ");
                 texiputchars(p, buf);                  texiputchars(p, buf);
                 if ( ! last)                  if ( ! last)
                         texiputchars(p, " ;");                          texiputchars(p, " ;");
                 teximacroclose(p);                  teximacroclose(p);
         }          }
   
         /* Print a reference to the next node. */          if (-1 != p->nodecache[p->nodecur].next) {
         if ( ! last) {                  texiputchars(p, "next node,");
                 if (1 == p->chapnum)                  snprintf(buf, sizeof(buf), "%s-%zd 7",
                         texiputchars(p, "Next node,");                          p->chapters, p->nodecache[p->nodecur].next);
                 else                  p->seenvs = 0;
                         texiputchars(p, "next node,");  
                 snprintf(buf, sizeof(buf),  
                         "node%zu 7", p->chapnum + 1);  
                 teximacroopen(p, "Xr ");                  teximacroopen(p, "Xr ");
                 texiputchars(p, buf);                  texiputchars(p, buf);
                 teximacroclose(p);                  teximacroclose(p);
         }          }
   
         fclose(p->outfile);          fclose(p->outfile);
           p->outfile = NULL;
 }  }
   
   ssize_t
   texicache(struct texi *p, const char *buf, size_t sz)
   {
           size_t i;
   
           for (i = 0; i < p->nodecachesz; i++) {
                   if (sz != strlen(p->nodecache[i].name))
                           continue;
                   if (strncmp(buf, p->nodecache[i].name, sz))
                           continue;
                   break;
           }
           if (i < p->nodecachesz)
                   return(i);
           if (NULL == buf)
                   return(-1);
           p->nodecache = realloc
                   (p->nodecache,
                    (p->nodecachesz + 1) * sizeof(struct texinode));
           if (NULL == p->nodecache)
                   texiabort(p, NULL);
           p->nodecache[p->nodecachesz].name = malloc(sz + 1);
           if (NULL == p->nodecache[p->nodecachesz].name)
                   texiabort(p, NULL);
           memcpy(p->nodecache[p->nodecachesz].name, buf, sz);
           p->nodecache[p->nodecachesz].name[sz] = '\0';
           p->nodecache[p->nodecachesz].up =
                   p->nodecache[p->nodecachesz].next =
                   p->nodecache[p->nodecachesz].prev = -1;
           p->nodecachesz++;
           return(p->nodecachesz - 1);
   }
   
 /*  /*
  * Open a mdoc(7) context.   * Here we print our standard mdoc(7) prologue.
  * If we're printing chapters, then open the outfile here, too.   * We use the title set with @settitle for the `Nd' description
  * Otherwise just print the mdoc(7) prologue.   * and the source document filename (the first one as invoked on
    * the command line) for the title.
    * The date is set to the current date.
  */   */
 void  void
 teximdocopen(struct texi *p, size_t *pos)  teximdocopen(struct texi *p, size_t *pos)
Line 1557  teximdocopen(struct texi *p, size_t *pos)
Line 1739  teximdocopen(struct texi *p, size_t *pos)
         const char      *cp;          const char      *cp;
         time_t           t;          time_t           t;
         char             date[32];          char             date[32];
         char             fname[PATH_MAX];  
   
         if (NULL != p->chapters) {  
                 snprintf(fname, sizeof(fname), "%s/node%zu.7",  
                         p->chapters, ++p->chapnum);  
                 p->outfile = fopen(fname, "w");  
                 if (NULL == p->outfile)  
                         texiabort(p, fname);  
         }  
   
         /*  
          * Here we print our standard mdoc(7) prologue.  
          * We use the title set with @settitle for the `Nd' description  
          * and the source document filename (the first one as invoked on  
          * the command line) for the title.  
          * The date is set to the current date.  
          */  
         t = time(NULL);          t = time(NULL);
         strftime(date, sizeof(date), "%F", localtime(&t));          strftime(date, sizeof(date), "%F", localtime(&t));
   
           p->seenvs = -1;
         teximacroopen(p, "Dd");          teximacroopen(p, "Dd");
         texiputchars(p, date);          texiputchars(p, date);
         teximacroclose(p);          teximacroclose(p);

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.34

CVSweb