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

Diff for /texi2mdoc/util.c between version 1.7 and 1.13

version 1.7, 2015/02/23 11:44:30 version 1.13, 2015/02/24 14:35:40
Line 43  texifilepop(struct texi *p)
Line 43  texifilepop(struct texi *p)
   
         assert(p->filepos > 0);          assert(p->filepos > 0);
         f = &p->files[--p->filepos];          f = &p->files[--p->filepos];
         munmap(f->map, f->mapsz);          if (TEXISRC_FILE == f->type)
                   munmap(f->map, f->mapsz);
           else
                   free(f->map);
 }  }
   
 static void  static void
Line 157  texierr(struct texi *p, const char *fmt, ...)
Line 160  texierr(struct texi *p, const char *fmt, ...)
   
 /*  /*
  * Put a single data character to the output if we're not ignoring.   * Put a single data character to the output if we're not ignoring.
  * Makes sure we don't spurriously start a macro.   * Escape starting a line with a control character and slashes.
  * Adjusts our output status.  
  * This shouldn't be called for macros: just for ordinary text.  
  */   */
 void  void
 texiputchar(struct texi *p, char c)  texiputchar(struct texi *p, char c)
Line 167  texiputchar(struct texi *p, char c)
Line 168  texiputchar(struct texi *p, char c)
   
         if (p->ign)          if (p->ign)
                 return;                  return;
   
         if ('.' == c && 0 == p->outcol)          if ('.' == c && 0 == p->outcol)
                 fputs("\\&", stdout);                  fputs("\\&", stdout);
           if ('\'' == c && 0 == p->outcol)
                   fputs("\\&", stdout);
   
         putchar(c);          putchar(c);
           if ('\\' == c)
                   putchar('e');
         p->seenvs = 0;          p->seenvs = 0;
         if ('\n' == c) {          if ('\n' == c) {
                 p->outcol = 0;                  p->outcol = 0;
Line 181  texiputchar(struct texi *p, char c)
Line 185  texiputchar(struct texi *p, char c)
 }  }
   
 /*  /*
  * Put multiple characters (see texiputchar()).   * Put an opaque series of characters.
  * This shouldn't be called for macros: just for ordinary text.   * Characters starting a line with a control character are escaped, but
    * that's it, so don't use this for non-controlled sequences of text.
  */   */
 void  void
 texiputchars(struct texi *p, const char *s)  texiputchars(struct texi *p, const char *s)
 {  {
   
         while ('\0' != *s)          if (p->ign)
                 texiputchar(p, *s++);                  return;
           if ('.' == *s && 0 == p->outcol)
                   fputs("\\&", stdout);
           if ('\'' == *s && 0 == p->outcol)
                   fputs("\\&", stdout);
           p->outcol += fputs(s, stdout);
           p->seenvs = 0;
 }  }
   
 /*  /*
    * This puts all characters onto the output stream but makes sure to
    * escape mdoc(7) slashes.
    */
   void
   texiputbuf(struct texi *p, const char *buf, size_t start, size_t end)
   {
   
           for ( ; start < end; start++) {
                   texiputchar(p, buf[start]);
                   if ('\\' == buf[start])
                           texiputchar(p, 'e');
           }
   }
   
   /*
  * Close an mdoc(7) macro opened with teximacroopen().   * Close an mdoc(7) macro opened with teximacroopen().
  * If there are no more macros on the line, prints a newline.   * If there are no more macros on the line, prints a newline.
  */   */
Line 347  advancenext(struct texi *p, const char *buf, size_t sz
Line 373  advancenext(struct texi *p, const char *buf, size_t sz
   
         if (p->literal) {          if (p->literal) {
                 while (*pos < sz && ismspace(buf[*pos])) {                  while (*pos < sz && ismspace(buf[*pos])) {
                         if (*pos && '\n' == buf[*pos] &&  
                                 '\\' == buf[*pos - 1])  
                                 texiputchar(p, 'e');  
                         texiputchar(p, buf[*pos]);                          texiputchar(p, buf[*pos]);
                         advance(p, buf, pos);                          advance(p, buf, pos);
                 }                  }
Line 404  static void
Line 427  static void
 texiexecmacro(struct texi *p, struct teximacro *m,  texiexecmacro(struct texi *p, struct teximacro *m,
         const char *buf, size_t sz, size_t *pos)          const char *buf, size_t sz, 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;
           const char       *cp;
   
         args = argparse(p, buf, sz, pos, &asz);          args = argparse(p, buf, sz, pos, &asz, m->argsz);
         if (asz != m->argsz)          if (asz != m->argsz)
                 texiwarn(p, "invalid macro argument length");                  texiwarn(p, "invalid macro argument length");
         aasz = asz < m->argsz ? asz : m->argsz;          aasz = asz < m->argsz ? asz : m->argsz;
   
         if (0 == aasz) {          if (0 == aasz) {
                 parseeof(p, m->value, strlen(m->value));                  parsemembuf(p, m->value, strlen(m->value));
                 return;                  return;
         }          }
   
Line 477  texiexecmacro(struct texi *p, struct teximacro *m,
Line 501  texiexecmacro(struct texi *p, struct teximacro *m,
                                 texiabort(p, NULL);                                  texiabort(p, NULL);
                 }                  }
   
                 j = strlcat(val, args[k], valsz + 1);                  for (cp = args[k]; '\0' != *cp; cp++)
                           val[j++] = *cp;
   
                   val[j] = '\0';
                 i = end;                  i = end;
         }          }
   
         parseeof(p, val, strlen(val));          parsemembuf(p, val, strlen(val));
   
         for (i = 0; i < asz; i++)          for (i = 0; i < asz; i++)
                 free(args[i]);                  free(args[i]);
Line 839  parseeof(struct texi *p, const char *buf, size_t sz)
Line 866  parseeof(struct texi *p, const char *buf, size_t sz)
 }  }
   
 /*  /*
    * This is like parseeof() except that it's to be invoked on memory
    * buffers while parsing a larger scope.
    * This is useful for parsing macro sequences.
    * The line, column, and name of the calling file context are saved, the
    * column and line reset, then all of these restored after parse.
    */
   void
   parsemembuf(struct texi *p, const char *buf, size_t sz)
   {
           size_t           svln, svcol;
           const char      *svname;
   
           svln = p->files[p->filepos - 1].line;
           svcol = p->files[p->filepos - 1].col;
           svname = p->files[p->filepos - 1].name;
   
           p->files[p->filepos - 1].line = 0;
           p->files[p->filepos - 1].col = 0;
           p->files[p->filepos - 1].name = "<macro buffer>";
   
           parseeof(p, buf, sz);
   
           p->files[p->filepos - 1].line = svln;
           p->files[p->filepos - 1].col = svcol;
           p->files[p->filepos - 1].name = svname;
   }
   
   /*
  * Parse a block sequence until we have the "@end endtoken" command   * Parse a block sequence until we have the "@end endtoken" command
  * invocation.   * invocation.
  * This will return immediately at EOF.   * This will return immediately at EOF.
Line 903  parseto(struct texi *p, const char *buf, 
Line 958  parseto(struct texi *p, const char *buf, 
 }  }
   
 /*  /*
    * Like parsefile() but used for reading from stdandard input.
    * This can only be called for the first file!
    */
   void
   parsestdin(struct texi *p)
   {
           struct texifile *f;
           size_t           off;
           ssize_t          ssz;
   
           assert(0 == p->filepos);
           f = &p->files[p->filepos];
           memset(f, 0, sizeof(struct texifile));
   
           f->type = TEXISRC_STDIN;
           f->name = "<stdin>";
   
           for (off = 0; ; off += (size_t)ssz) {
                   if (off == f->mapsz) {
                           if (f->mapsz == (1U << 31))
                                   texierr(p, "stdin buffer too long");
                           f->mapsz = f->mapsz > 65536 / 2 ?
                                   2 * f->mapsz : 65536;
                           f->map = realloc(f->map, f->mapsz);
                           if (NULL == f->map)
                                   texiabort(p, NULL);
                   }
                   ssz = read(STDIN_FILENO,
                           f->map + (int)off, f->mapsz - off);
                   if (0 == ssz)
                           break;
                   else if (-1 == ssz)
                           texiabort(p, NULL);
           }
   
           p->filepos++;
           parseeof(p, f->map, off);
           texifilepop(p);
   }
   
   /*
  * Memory-map the file "fname" and begin parsing it unless "parse" is   * Memory-map the file "fname" and begin parsing it unless "parse" is
  * zero, in which case we just dump the file to stdout (making sure it   * zero, in which case we just dump the file to stdout (making sure it
  * doesn't trip up mdoc(7) along the way).   * doesn't trip up mdoc(7) along the way).
Line 921  parsefile(struct texi *p, const char *fname, int parse
Line 1017  parsefile(struct texi *p, const char *fname, int parse
         f = &p->files[p->filepos];          f = &p->files[p->filepos];
         memset(f, 0, sizeof(struct texifile));          memset(f, 0, sizeof(struct texifile));
   
           f->type = TEXISRC_FILE;
         f->name = fname;          f->name = fname;
         if (-1 == (fd = open(fname, O_RDONLY, 0))) {          if (-1 == (fd = open(fname, O_RDONLY, 0))) {
                 texiabort(p, fname);                  texiabort(p, fname);
Line 939  parsefile(struct texi *p, const char *fname, int parse
Line 1036  parsefile(struct texi *p, const char *fname, int parse
   
         p->filepos++;          p->filepos++;
         if ( ! parse) {          if ( ! parse) {
                 /*                  for (i = 0; i < f->mapsz; i++)
                  * We're printing verbatim output.                          texiputchar(p, f->map[i]);
                  * Make sure it doesn't get interpreted as mdoc by                  if (p->outcol)
                  * escaping escapes and making sure leading dots don't                          texiputchar(p, '\n');
                  * trigger mdoc(7) expansion.  
                  */  
                 for (i = 0; i < f->mapsz; i++) {  
                         if (i > 0 && '.' == f->map[i])  
                                 if ('\n' == f->map[i - 1])  
                                         fputs("\\&", stdout);  
                         putchar(f->map[i]);  
                         if ('\\' == f->map[i])  
                                 putchar('e');  
                 }  
         } else          } else
                 parseeof(p, f->map, f->mapsz);                  parseeof(p, f->map, f->mapsz);
         texifilepop(p);          texifilepop(p);
Line 1104  valueadd(struct texi *p, char *key, char *val)
Line 1191  valueadd(struct texi *p, char *key, char *val)
  */   */
 char **  char **
 argparse(struct texi *p, const char *buf,  argparse(struct texi *p, const char *buf,
         size_t sz, size_t *pos, size_t *argsz)          size_t sz, size_t *pos, size_t *argsz, size_t hint)
 {  {
         char    **args;          char    **args;
         size_t    start, end, stack;          size_t    start, end, stack;
Line 1115  argparse(struct texi *p, const char *buf, 
Line 1202  argparse(struct texi *p, const char *buf, 
         args = NULL;          args = NULL;
         *argsz = 0;          *argsz = 0;
   
         /* Check for no arguments. */          if ('{' != buf[*pos] && hint) {
         if ('{' != buf[*pos])                  /*
                    * Special case: if we encounter an unbracketed argument
                    * and we're being invoked with non-zero arguments
                    * (versus being set, i.e., hint>0), then parse until
                    * the end of line.
                    */
                   *argsz = 1;
                   args = calloc(1, sizeof(char *));
                   if (NULL == args)
                           texiabort(p, NULL);
                   start = *pos;
                   while (*pos < sz) {
                           if ('\n' == buf[*pos])
                                   break;
                           advance(p, buf, pos);
                   }
                   args[0] = malloc(*pos - start + 1);
                   memcpy(args[0], &buf[start], *pos - start);
                   args[0][*pos - start] = '\0';
                   if (*pos < sz && '\n' == buf[*pos])
                           advance(p, buf, pos);
                 return(args);                  return(args);
           } else if ('{' != buf[*pos])
                   return(args);
   
         /* Parse til the closing '}', putting into the array. */          /* Parse til the closing '}', putting into the array. */
         advance(p, buf, pos);          advance(p, buf, pos);
Line 1133  argparse(struct texi *p, const char *buf, 
Line 1242  argparse(struct texi *p, const char *buf, 
                          * We keep track of embedded-ness in the "stack"                           * We keep track of embedded-ness in the "stack"
                          * state anyway, so this is free.                           * state anyway, so this is free.
                          */                           */
                         if (0 == stack && ',' == buf[*pos])                          if (',' == buf[*pos] && 0 == stack && 1 != hint)
                                 break;                                  break;
                         else if (0 == stack && '}' == buf[*pos])                          else if (0 == stack && '}' == buf[*pos])
                                 break;                                  break;
Line 1151  argparse(struct texi *p, const char *buf, 
Line 1260  argparse(struct texi *p, const char *buf, 
                 /* Test for zero-length '{  }'. */                  /* Test for zero-length '{  }'. */
                 if (start == end && '}' == buf[*pos] && 0 == *argsz)                  if (start == end && '}' == buf[*pos] && 0 == *argsz)
                         break;                          break;
                 if (start == end)  
                         texierr(p, "zero-length argument");  
                 /* FIXME: use reallocarray. */                  /* FIXME: use reallocarray. */
                 args = realloc                  args = realloc
                         (args, sizeof(char *) *                          (args, sizeof(char *) *

Legend:
Removed from v.1.7  
changed lines
  Added in v.1.13

CVSweb