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

Diff for /mandoc/out.c between version 1.4 and 1.16

version 1.4, 2009/10/09 06:54:11 version 1.16, 2010/06/19 20:46:28
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>   * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above   * purpose with or without fee is hereby granted, provided that the above
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.
  */   */
   #ifdef HAVE_CONFIG_H
   #include "config.h"
   #endif
   
 #include <sys/types.h>  #include <sys/types.h>
   
   #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <string.h>
   #include <time.h>
   
 #include "out.h"  #include "out.h"
   
   /* See a2roffdeco(). */
   #define C2LIM(c, l) do { \
           (l) = 1; \
           if ('[' == (c) || '\'' == (c)) \
                   (l) = 0; \
           else if ('(' == (c)) \
                   (l) = 2; } \
           while (/* CONSTCOND */ 0)
   
   /* See a2roffdeco(). */
   #define C2TERM(c, t) do { \
           (t) = 0; \
           if ('\'' == (c)) \
                   (t) = 1; \
           else if ('[' == (c)) \
                   (t) = 2; \
           else if ('(' == (c)) \
                   (t) = 3; } \
           while (/* CONSTCOND */ 0)
   
 /*  /*
  * Convert a `scaling unit' to a consistent form, or fail.  Scaling   * Convert a `scaling unit' to a consistent form, or fail.  Scaling
  * units are documented in groff.7, which stipulates the following:   * units are documented in groff.7, mdoc.7, man.7.
  *  
  *  (1) A scaling unit is a signed/unsigned integer/float with or  
  *      without a unit.  
  *  
  *  (2) The following units exist:  
  *      c       Centimeter  
  *      i       Inch  
  *      P       Pica = 1/6 inch  
  *      p       Point = 1/72 inch  
  *      m       Em = the font size in points (width of letter m)  
  *      M       100th of an Em  
  *      n       En = Em/2  
  *      u       Basic unit for actual output device  
  *      v       Vertical line space in basic units scaled point =  
  *              1/sizescale of a point (defined in font DESC file)  
  *      f       Scale by 65536.  
  */   */
 int  int
 a2roffsu(const char *src, struct roffsu *dst)  a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
 {  {
         char             buf[BUFSIZ], hasd;          char             buf[BUFSIZ], hasd;
         int              i;          int              i;
         enum roffscale   unit;          enum roffscale   unit;
   
           if ('\0' == *src)
                   return(0);
   
         i = hasd = 0;          i = hasd = 0;
   
         switch (*src) {          switch (*src) {
Line 63  a2roffsu(const char *src, struct roffsu *dst)
Line 76  a2roffsu(const char *src, struct roffsu *dst)
                 break;                  break;
         }          }
   
           if ('\0' == *src)
                   return(0);
   
         while (i < BUFSIZ) {          while (i < BUFSIZ) {
                 if ( ! isdigit((u_char)*src)) {                  if ( ! isdigit((u_char)*src)) {
                         if ('.' != *src)                          if ('.' != *src)
Line 103  a2roffsu(const char *src, struct roffsu *dst)
Line 119  a2roffsu(const char *src, struct roffsu *dst)
                 unit = SCALE_EM;                  unit = SCALE_EM;
                 break;                  break;
         case ('\0'):          case ('\0'):
                 /* FALLTHROUGH */                  if (SCALE_MAX == def)
                           return(0);
                   unit = SCALE_BU;
                   break;
         case ('u'):          case ('u'):
                 unit = SCALE_BU;                  unit = SCALE_BU;
                 break;                  break;
Line 122  a2roffsu(const char *src, struct roffsu *dst)
Line 141  a2roffsu(const char *src, struct roffsu *dst)
         dst->unit = unit;          dst->unit = unit;
         dst->pt = hasd;          dst->pt = hasd;
   
           return(1);
   }
   
   
   /*
    * Correctly writes the time in nroff form, which differs from standard
    * form in that a space isn't printed in lieu of the extra %e field for
    * single-digit dates.
    */
   void
   time2a(time_t t, char *dst, size_t sz)
   {
           struct tm        tm;
           char             buf[5];
           char            *p;
           size_t           nsz;
   
           assert(sz > 1);
           localtime_r(&t, &tm);
   
           p = dst;
           nsz = 0;
   
           dst[0] = '\0';
   
           if (0 == (nsz = strftime(p, sz, "%B ", &tm)))
                   return;
   
           p += (int)nsz;
           sz -= nsz;
   
           if (0 == strftime(buf, sizeof(buf), "%e, ", &tm))
                   return;
   
           nsz = strlcat(p, buf + (' ' == buf[0] ? 1 : 0), sz);
   
           if (nsz >= sz)
                   return;
   
           p += (int)nsz;
           sz -= nsz;
   
           (void)strftime(p, sz, "%Y", &tm);
   }
   
   
   /*
    * Returns length of parsed string (the leading "\" should NOT be
    * included).  This can be zero if the current character is the nil
    * terminator.  "d" is set to the type of parsed decorator, which may
    * have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2).
    */
   int
   a2roffdeco(enum roffdeco *d,
                   const char **word, size_t *sz)
   {
           int              j, term, lim;
           char             set;
           const char      *wp, *sp;
   
           *d = DECO_NONE;
           wp = *word;
   
           switch ((set = *wp)) {
           case ('\0'):
                   return(0);
   
           case ('('):
                   if ('\0' == *(++wp))
                           return(1);
                   if ('\0' == *(wp + 1))
                           return(2);
   
                   *d = DECO_SPECIAL;
                   *sz = 2;
                   *word = wp;
                   return(3);
   
           case ('F'):
                   /* FALLTHROUGH */
           case ('f'):
                   /*
                    * FIXME: this needs work and consolidation (it should
                    * follow the sequence that special characters do, for
                    * one), but isn't a priority at the moment.  Note, for
                    * one, that in reality \fB != \FB, although here we let
                    * these slip by.
                    */
                   switch (*(++wp)) {
                   case ('\0'):
                           return(1);
                   case ('3'):
                           /* FALLTHROUGH */
                   case ('B'):
                           *d = DECO_BOLD;
                           return(2);
                   case ('2'):
                           /* FALLTHROUGH */
                   case ('I'):
                           *d = DECO_ITALIC;
                           return(2);
                   case ('P'):
                           *d = DECO_PREVIOUS;
                           return(2);
                   case ('1'):
                           /* FALLTHROUGH */
                   case ('R'):
                           *d = DECO_ROMAN;
                           return(2);
                   case ('('):
                           if ('\0' == *(++wp))
                                   return(2);
                           if ('\0' == *(wp + 1))
                                   return(3);
   
                           *d = 'F' == set ? DECO_FFONT : DECO_FONT;
                           *sz = 2;
                           *word = wp;
                           return(4);
                   case ('['):
                           *word = ++wp;
                           for (j = 0; *wp && ']' != *wp; wp++, j++)
                                   /* Loop... */ ;
   
                           if ('\0' == *wp)
                                   return(j + 2);
   
                           *d = 'F' == set ? DECO_FFONT : DECO_FONT;
                           *sz = (size_t)j;
                           return(j + 3);
                   default:
                           break;
                   }
   
                   *d = 'F' == set ? DECO_FFONT : DECO_FONT;
                   *sz = 1;
                   *word = wp;
                   return(2);
   
           case ('*'):
                   switch (*(++wp)) {
                   case ('\0'):
                           return(1);
   
                   case ('('):
                           if ('\0' == *(++wp))
                                   return(2);
                           if ('\0' == *(wp + 1))
                                   return(3);
   
                           *d = DECO_RESERVED;
                           *sz = 2;
                           *word = wp;
                           return(4);
   
                   case ('['):
                           *word = ++wp;
                           for (j = 0; *wp && ']' != *wp; wp++, j++)
                                   /* Loop... */ ;
   
                           if ('\0' == *wp)
                                   return(j + 2);
   
                           *d = DECO_RESERVED;
                           *sz = (size_t)j;
                           return(j + 3);
   
                   default:
                           break;
                   }
   
                   *d = DECO_RESERVED;
                   *sz = 1;
                   *word = wp;
                   return(2);
   
           case ('s'):
                   sp = wp;
                   if ('\0' == *(++wp))
                           return(1);
   
                   C2LIM(*wp, lim);
                   C2TERM(*wp, term);
   
                   if (term)
                           wp++;
   
                   *word = wp;
   
                   if (*wp == '+' || *wp == '-')
                           ++wp;
   
                   switch (*wp) {
                   case ('\''):
                           /* FALLTHROUGH */
                   case ('['):
                           /* FALLTHROUGH */
                   case ('('):
                           if (term)
                                   return((int)(wp - sp));
   
                           C2LIM(*wp, lim);
                           C2TERM(*wp, term);
                           wp++;
                           break;
                   default:
                           break;
                   }
   
                   if ( ! isdigit((u_char)*wp))
                           return((int)(wp - sp));
   
                   for (j = 0; isdigit((u_char)*wp); j++) {
                           if (lim && j >= lim)
                                   break;
                           ++wp;
                   }
   
                   if (term && term < 3) {
                           if (1 == term && *wp != '\'')
                                   return((int)(wp - sp));
                           if (2 == term && *wp != ']')
                                   return((int)(wp - sp));
                           ++wp;
                   }
   
                   *d = DECO_SIZE;
                   return((int)(wp - sp));
   
           case ('['):
                   *word = ++wp;
   
                   for (j = 0; *wp && ']' != *wp; wp++, j++)
                           /* Loop... */ ;
   
                   if ('\0' == *wp)
                           return(j + 1);
   
                   *d = DECO_SPECIAL;
                   *sz = (size_t)j;
                   return(j + 2);
   
           case ('c'):
                   *d = DECO_NOSPACE;
                   *sz = 1;
                   return(1);
   
           default:
                   break;
           }
   
           *d = DECO_SPECIAL;
           *word = wp;
           *sz = 1;
         return(1);          return(1);
 }  }

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.16

CVSweb