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

Diff for /texi2mdoc/util.c between version 1.17 and 1.20

version 1.17, 2015/02/28 00:03:20 version 1.20, 2015/03/01 00:25:08
Line 20 
Line 20 
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
 #include <fcntl.h>  #include <fcntl.h>
 #include <getopt.h>  
 #include <libgen.h>  
 #include <limits.h>  #include <limits.h>
 #include <stdarg.h>  #include <stdarg.h>
 #include <stdio.h>  #include <stdio.h>
Line 79  texiexit(struct texi *p)
Line 77  texiexit(struct texi *p)
   
         /* Make sure we're newline-terminated. */          /* Make sure we're newline-terminated. */
         if (p->outcol)          if (p->outcol)
                 putchar('\n');                  fputc('\n', p->outfile);
           if (NULL != p->chapters)
                   teximdocclose(p, 1);
   
         /* Unmap all files. */          /* Unmap all files. */
         while (p->filepos > 0)          while (p->filepos > 0)
Line 180  texiputchar(struct texi *p, char c)
Line 180  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("\\&", p->outfile);
         if ('\'' == c && 0 == p->outcol)          if ('\'' == c && 0 == p->outcol)
                 fputs("\\&", stdout);                  fputs("\\&", p->outfile);
   
         putchar(c);          fputc(c, p->outfile);
         if ('\\' == c)          if ('\\' == c)
                 putchar('e');                  fputc('e', p->outfile);
         p->seenvs = 0;          p->seenvs = 0;
         if ('\n' == c) {          if ('\n' == c) {
                 p->outcol = 0;                  p->outcol = 0;
Line 207  texiputchars(struct texi *p, const char *s)
Line 207  texiputchars(struct texi *p, const char *s)
         if (p->ign)          if (p->ign)
                 return;                  return;
         if ('.' == *s && 0 == p->outcol)          if ('.' == *s && 0 == p->outcol)
                 fputs("\\&", stdout);                  fputs("\\&", p->outfile);
         if ('\'' == *s && 0 == p->outcol)          if ('\'' == *s && 0 == p->outcol)
                 fputs("\\&", stdout);                  fputs("\\&", p->outfile);
         p->outcol += fputs(s, stdout);          p->outcol += fputs(s, p->outfile);
         p->seenvs = 0;          p->seenvs = 0;
 }  }
   
Line 239  teximacroclose(struct texi *p)
Line 239  teximacroclose(struct texi *p)
                 return;                  return;
   
         if (0 == --p->outmacro) {          if (0 == --p->outmacro) {
                 putchar('\n');                  fputc('\n', p->outfile);
                 p->outcol = p->seenws = 0;                  p->outcol = p->seenws = 0;
         }          }
 }  }
Line 259  teximacroopen(struct texi *p, const char *s)
Line 259  teximacroopen(struct texi *p, const char *s)
                 return;                  return;
   
         if (p->outcol && 0 == p->outmacro) {          if (p->outcol && 0 == p->outmacro) {
                 putchar('\n');                  fputc('\n', p->outfile);
                 p->outcol = 0;                  p->outcol = 0;
         }          }
   
         if (0 == p->outmacro)          if (0 == p->outmacro)
                 putchar('.');                  fputc('.', p->outfile);
         else          else
                 putchar(' ');                  fputc(' ', p->outfile);
   
         if (EOF != (rc = fputs(s, stdout)))          if (EOF != (rc = fputs(s, p->outfile)))
                 p->outcol += rc;                  p->outcol += rc;
   
         putchar(' ');          fputc(' ', p->outfile);
         p->outcol++;          p->outcol++;
         p->outmacro++;          p->outmacro++;
         p->seenws = 0;          p->seenws = 0;
Line 293  teximacro(struct texi *p, const char *s)
Line 293  teximacro(struct texi *p, const char *s)
                 texierr(p, "\"%s\" in a literal scope!?", s);                  texierr(p, "\"%s\" in a literal scope!?", s);
   
         if (p->outcol)          if (p->outcol)
                 putchar('\n');                  fputc('\n', p->outfile);
   
         putchar('.');          fputc('.', p->outfile);
         puts(s);          fputs(s, p->outfile);
           fputc('\n', p->outfile);
         p->outcol = p->seenws = 0;          p->outcol = p->seenws = 0;
 }  }
   
Line 591  parseword(struct texi *p, size_t *pos, char extra)
Line 592  parseword(struct texi *p, size_t *pos, char extra)
  * index after the command name.   * index after the command name.
  */   */
 enum texicmd  enum texicmd
 texicmd(struct texi *p, size_t pos, size_t *end, struct teximacro **macro)  texicmd(const struct texi *p, size_t pos, size_t *end, struct teximacro **macro)
 {  {
         size_t   i, len, toksz;          size_t   i, len, toksz;
   
Line 719  parsearg(struct texi *p, size_t *pos, size_t num)
Line 720  parsearg(struct texi *p, size_t *pos, size_t num)
  * This will stop in the event of EOF or if we're not at a bracket.   * This will stop in the event of EOF or if we're not at a bracket.
  */   */
 void  void
 parsebracket(struct texi *p, size_t *pos)  parsebracket(struct texi *p, size_t *pos, int dostack)
 {  {
         size_t            end, sv;          size_t            end, sv, stack;
         enum texicmd      cmd;          enum texicmd      cmd;
         struct teximacro *macro;          struct teximacro *macro;
   
Line 732  parsebracket(struct texi *p, size_t *pos)
Line 733  parsebracket(struct texi *p, size_t *pos)
                 return;                  return;
         advance(p, pos);          advance(p, pos);
   
           stack = 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 ('}'):
                           if (stack > 0) {
                                   stack--;
                                   advance(p, pos);
                                   texiputchar(p, '}');
                                   continue;
                           }
                         advance(p, pos);                          advance(p, pos);
                         return;                          return;
                 case ('{'):                  case ('{'):
                           if (dostack) {
                                   stack++;
                                   advance(p, pos);
                                   texiputchar(p, '{');
                                   continue;
                           }
                         if (0 == p->ign)                          if (0 == p->ign)
                                 texiwarn(p, "unexpected \"{\"");                                  texiwarn(p, "unexpected \"{\"");
                         advance(p, pos);                          advance(p, pos);
Line 814  parseeoln(struct texi *p, size_t *pos)
Line 828  parseeoln(struct texi *p, size_t *pos)
 }  }
   
 /*  /*
    * Peek to see if there's a command after subsequent whitespace.
    * If so, return the macro identifier.
    * This DOES NOT work with user-defined macros.
    */
   enum texicmd
   peekcmd(const struct texi *p, size_t pos)
   {
           size_t          end;
   
           while (pos < BUFSZ(p) && ismspace(BUF(p)[pos]))
                   pos++;
           if (pos == BUFSZ(p) || '@' != BUF(p)[pos])
                   return(TEXICMD__MAX);
           return(texicmd(p, pos, &end, NULL));
   }
   
   /*
  * 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.
  */   */
Line 874  parselinearg(struct texi *p, size_t *pos)
Line 905  parselinearg(struct texi *p, size_t *pos)
         }          }
   
         if (*pos < BUFSZ(p) && '{' == BUF(p)[*pos])          if (*pos < BUFSZ(p) && '{' == BUF(p)[*pos])
                 parsebracket(p, pos);                  parsebracket(p, pos, 0);
         else if (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos])          else if (*pos < BUFSZ(p) && '\n' != BUF(p)[*pos])
                 parsesingle(p, pos);                  parsesingle(p, pos);
         else          else
Line 1318  argparse(struct texi *p, size_t *pos, size_t *argsz, s
Line 1349  argparse(struct texi *p, size_t *pos, size_t *argsz, s
         advance(p, pos);          advance(p, pos);
         return(args);          return(args);
 }  }
   
   /*
    * If we're printing chapters, then do some naviation here and then
    * close our outfile.
    * I want to call this the SEE ALSO section, but that's not really what
    * it is: we'll refer to the "initial" (top) node and the next and
    * previous chapters.
    */
   void
   teximdocclose(struct texi *p, int last)
   {
           char     buf[PATH_MAX];
   
           if (NULL == p->chapters || 0 == p->chapnum)
                   return;
   
           teximacro(p, "Sh INFO NAVIGATION");
   
           /* Print a reference to the "top" node. */
           if (p->chapnum > 1) {
                   snprintf(buf, sizeof(buf), "node1 7");
                   teximacroopen(p, "Xr ");
                   texiputchars(p, buf);
                   texiputchars(p, " ,");
                   teximacroclose(p);
           }
   
           /* Print a reference to the previous node. */
           if (p->chapnum > 2) {
                   snprintf(buf, sizeof(buf),
                           "node%zu 7", p->chapnum - 1);
                   teximacroopen(p, "Xr ");
                   texiputchars(p, buf);
                   if ( ! last)
                           texiputchars(p, " ,");
                   teximacroclose(p);
           }
   
           /* Print a reference to the next node. */
           if ( ! last) {
                   snprintf(buf, sizeof(buf),
                           "node%zu 7", p->chapnum + 1);
                   teximacroopen(p, "Xr ");
                   texiputchars(p, buf);
                   teximacroclose(p);
           }
   
           fclose(p->outfile);
   }
   
   /*
    * Open a mdoc(7) context.
    * If we're printing chapters, then open the outfile here, too.
    * Otherwise just print the mdoc(7) prologue.
    */
   void
   teximdocopen(struct texi *p)
   {
           const char      *cp;
           time_t           t;
           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);
           strftime(date, sizeof(date), "%F", localtime(&t));
   
           teximacroopen(p, "Dd");
           texiputchars(p, date);
           teximacroclose(p);
           teximacroopen(p, "Dt");
           for (cp = p->title; '\0' != *cp; cp++)
                   texiputchar(p, toupper((unsigned int)*cp));
           texiputchars(p, " 7");
           teximacroclose(p);
           teximacro(p, "Os");
           teximacro(p, "Sh NAME");
           teximacroopen(p, "Nm");
           for (cp = p->title; '\0' != *cp; cp++)
                   texiputchar(p, *cp);
           teximacroclose(p);
           teximacroopen(p, "Nd");
           if (NULL != p->subtitle)
                   for (cp = p->subtitle; '\0' != *cp; cp++)
                           texiputchar(p, *cp);
           else
                   texiputchars(p, "Unknown description");
           teximacroclose(p);
           p->seenvs = 1;
   }
   

Legend:
Removed from v.1.17  
changed lines
  Added in v.1.20

CVSweb