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

Diff for /mandoc/Attic/mdocml.c between version 1.2 and 1.20

version 1.2, 2008/11/22 16:55:02 version 1.20, 2008/12/10 14:42:46
Line 30 
Line 30 
   
 #include "libmdocml.h"  #include "libmdocml.h"
   
 struct md_file {  #define BUFFER_IN_DEF   BUFSIZ   /* See begin_bufs. */
         int              fd;  #define BUFFER_OUT_DEF  BUFSIZ   /* See begin_bufs. */
         const char      *name;  
 };  
   
 struct md_buf {  #ifdef  DEBUG
         struct md_file  *file;  #define CSS             "mdocml.css"
         char            *buf;  #else
         size_t           bufsz;  #define CSS             "/usr/local/share/mdocml/mdocml.css"
         size_t           line;  #endif
 };  
   
 struct md_mbuf {  static  void             usage(void);
         struct md_buf   *buf;  
         size_t           pos;  
 };  
   
 static void              usage(void);  static  int              begin_io(const struct md_args *,
                                   char *, char *);
   static  int              leave_io(const struct md_buf *,
                                   const struct md_buf *, int);
   static  int              begin_bufs(const struct md_args *,
                                   struct md_buf *, struct md_buf *);
   static int               leave_bufs(const struct md_buf *,
                                   const struct md_buf *, int);
   
 static int               md_begin(const char *, const char *);  #ifdef __linux__
 static int               md_begin_io(const char *, const char *);  extern  int              getsubopt(char **, char *const *, char **);
 static int               md_begin_bufs(struct md_file *, struct md_file *);  #endif
 static int               md_run(struct md_buf *, struct md_buf *);  
 static int               md_line(struct md_mbuf *, const struct md_buf *,  
                                 const char *, size_t);  
   
 static ssize_t           md_buf_fill(struct md_buf *);  
 static int               md_buf_flush(struct md_mbuf *);  
   
 static int               md_buf_putchar(struct md_mbuf *, char);  
 static int               md_buf_puts(struct md_mbuf *,  
                                 const char *, size_t);  
   
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
 {  {
         int              c;          int              c;
         char            *out, *in;          char            *out, *in, *opts, *v;
           struct md_args   args;
   #define ALL              0
   #define ERROR            1
           char            *toks[] = { "all", "error", NULL };
   
         extern char     *optarg;          extern char     *optarg;
         extern int       optind;          extern int       optind;
   
         out = NULL;          out = in = NULL;
   
         while (-1 != (c = getopt(argc, argv, "o:")))          (void)memset(&args, 0, sizeof(struct md_args));
   
           args.type = MD_NOOP;
   
           while (-1 != (c = getopt(argc, argv, "c:ef:o:vW:")))
                 switch (c) {                  switch (c) {
                   case ('c'):
                           if (args.type != MD_HTML)
                                   errx(1, "-c only valid for -fhtml");
                           args.params.html.css = optarg;
                           break;
                   case ('e'):
                           if (args.type != MD_HTML)
                                   errx(1, "-e only valid for -fhtml");
                           args.params.html.flags |= HTML_CSS_EMBED;
                           break;
                   case ('f'):
                           if (0 == strcmp(optarg, "html"))
                                   args.type = MD_HTML;
                           else if (0 == strcmp(optarg, "xml"))
                                   args.type = MD_XML;
                           else if (0 == strcmp(optarg, "noop"))
                                   args.type = MD_NOOP;
                           else
                                   errx(1, "invalid filter type");
                           break;
                 case ('o'):                  case ('o'):
                         out = optarg;                          out = optarg;
                         break;                          break;
                   case ('v'):
                           args.verbosity++;
                           break;
                   case ('W'):
                           opts = optarg;
                           while (*opts)
                                   switch (getsubopt(&opts, toks, &v)) {
                                   case (ALL):
                                           args.warnings |= MD_WARN_ALL;
                                           break;
                                   case (ERROR):
                                           args.warnings |= MD_WARN_ERROR;
                                           break;
                                   default:
                                           usage();
                                           return(1);
                                   }
                           break;
                 default:                  default:
                         usage();                          usage();
                         return(1);                          return(1);
                 }                  }
   
           if (MD_HTML == args.type)
                   if (NULL == args.params.html.css)
                           args.params.html.css = CSS;
   
         argv += optind;          argv += optind;
         if (1 != (argc -= optind)) {          argc -= optind;
                 usage();  
                 return(1);  
         }  
   
         argc--;          if (1 == argc)
         in = *argv++;                  in = *argv++;
   
         return(md_begin(out, in));          return(begin_io(&args, out ? out : "-", in ? in : "-"));
 }  }
   
   
   /*
    * Close out file descriptors opened in begin_io.  If the descriptor
    * refers to stdin/stdout, then do nothing.
    */
 static int  static int
 md_begin(const char *out, const char *in)  leave_io(const struct md_buf *out,
                   const struct md_buf *in, int c)
 {  {
         char             buf[MAXPATHLEN];          assert(out);
   
         assert(in);          assert(in);
         if (out)  
                 return(md_begin_io(out, in));  
   
         if (strlcpy(buf, in, MAXPATHLEN) >= MAXPATHLEN)          if (-1 != in->fd && -1 == close(in->fd)) {
                 warnx("output filename too long");                  assert(in->name);
         else if (strlcat(buf, ".html", MAXPATHLEN) >= MAXPATHLEN)                  warn("%s", in->name);
                 warnx("output filename too long");                  c = 1;
         else          }
                 return(md_begin_io(buf, in));          if (-1 != out->fd && STDOUT_FILENO != out->fd &&
                           -1 == close(out->fd)) {
                   assert(out->name);
                   warn("%s", out->name);
                   c = 1;
           }
           if (1 == c && STDOUT_FILENO != out->fd)
                   if (-1 == unlink(out->name))
                           warn("%s", out->name);
   
         return(1);          return(c);
 }  }
   
   
   /*
    * Open file descriptors or assign stdin/stdout, if dictated by the "-"
    * token instead of a filename.
    */
 static int  static int
 md_begin_io(const char *out, const char *in)  begin_io(const struct md_args *args, char *out, char *in)
 {  {
         int              c;          struct md_buf    fi;
         struct md_file   fin, fout;          struct md_buf    fo;
   
   #define FI_FL   O_RDONLY
   #define FO_FL   O_WRONLY|O_CREAT|O_TRUNC
   
           assert(args);
         assert(out);          assert(out);
         assert(in);          assert(in);
   
         /* TODO: accept "-" as both input and output. */          bzero(&fi, sizeof(struct md_buf));
           bzero(&fo, sizeof(struct md_buf));
   
         fin.name = in;          fi.fd = STDIN_FILENO;
           fo.fd = STDOUT_FILENO;
   
         if (-1 == (fin.fd = open(fin.name, O_RDONLY, 0))) {          fi.name = in;
                 warn("%s", fin.name);          fo.name = out;
                 return(1);  
         }  
   
         fout.name = out;          if (0 != strncmp(fi.name, "-", 1))
                   if (-1 == (fi.fd = open(fi.name, FI_FL, 0))) {
                           warn("%s", fi.name);
                           return(leave_io(&fo, &fi, 1));
                   }
   
         fout.fd = open(fout.name, O_WRONLY | O_CREAT | O_TRUNC, 0644);          if (0 != strncmp(fo.name, "-", 1))
         if (-1 == fout.fd) {                  if (-1 == (fo.fd = open(fo.name, FO_FL, 0644))) {
                 warn("%s", fout.name);                          warn("%s", fo.name);
                 if (-1 == close(fin.fd))                          return(leave_io(&fo, &fi, 1));
                         warn("%s", fin.name);                  }
                 return(1);  
         }  
   
         c = md_begin_bufs(&fout, &fin);          return(leave_io(&fo, &fi, begin_bufs(args, &fo, &fi)));
   }
   
         if (-1 == close(fin.fd)) {  
                 warn("%s", in);  
                 c = 1;  
         }  
         if (-1 == close(fout.fd)) {  
                 warn("%s", out);  
                 c = 1;  
         }  
   
   /*
    * Free buffers allocated in begin_bufs.
    */
   static int
   leave_bufs(const struct md_buf *out,
                   const struct md_buf *in, int c)
   {
           assert(out);
           assert(in);
           if (out->buf)
                   free(out->buf);
           if (in->buf)
                   free(in->buf);
         return(c);          return(c);
 }  }
   
   
   /*
    * Allocate buffers to the maximum of either the input file's blocksize
    * or BUFFER_IN_DEF/BUFFER_OUT_DEF, which should be around BUFSIZE.
    */
 static int  static int
 md_begin_bufs(struct md_file *out, struct md_file *in)  begin_bufs(const struct md_args *args,
                   struct md_buf *out, struct md_buf *in)
 {  {
         struct stat      stin, stout;          struct stat      stin, stout;
         struct md_buf    inbuf, outbuf;  
         int              c;          int              c;
   
           assert(args);
         assert(in);          assert(in);
         assert(out);          assert(out);
   
         if (-1 == fstat(in->fd, &stin)) {          if (-1 == fstat(in->fd, &stin)) {
                 warn("fstat: %s", in->name);                  warn("%s", in->name);
                 return(1);                  return(1);
           } else if (STDIN_FILENO != in->fd && 0 == stin.st_size) {
                   warnx("%s: empty file", in->name);
                   return(1);
         } else if (-1 == fstat(out->fd, &stout)) {          } else if (-1 == fstat(out->fd, &stout)) {
                 warn("fstat: %s", out->name);                  warn("%s", out->name);
                 return(1);                  return(1);
         }          }
   
         inbuf.file = in;          in->bufsz = MAX(stin.st_blksize, BUFFER_IN_DEF);
         inbuf.line = 1;          out->bufsz = MAX(stout.st_blksize, BUFFER_OUT_DEF);
         /*inbuf.bufsz = MAX(stin.st_blksize, BUFSIZ);*/  
         inbuf.bufsz = 256;  
   
         outbuf.file = out;          if (NULL == (in->buf = malloc(in->bufsz))) {
         outbuf.line = 1;  
         /*outbuf.bufsz = MAX(stout.st_blksize, BUFSIZ);*/  
         outbuf.bufsz = 256;  
   
         if (NULL == (inbuf.buf = malloc(inbuf.bufsz))) {  
                 warn("malloc");                  warn("malloc");
                 return(1);                  return(leave_bufs(out, in, 1));
         } else if (NULL == (outbuf.buf = malloc(outbuf.bufsz))) {          } else if (NULL == (out->buf = malloc(out->bufsz))) {
                 warn("malloc");                  warn("malloc");
                 free(inbuf.buf);                  return(leave_bufs(out, in, 1));
                 return(1);  
         }          }
   
         c = md_run(&outbuf, &inbuf);          c = md_run(args, out, in);
           return(leave_bufs(out, in, -1 == c ? 1 : 0));
         free(inbuf.buf);  
         free(outbuf.buf);  
   
         return(c);  
 }  }
   
   
 static ssize_t  
 md_buf_fill(struct md_buf *in)  
 {  
         ssize_t          ssz;  
   
         assert(in);  
         assert(in->file);  
         assert(in->buf);  
         assert(in->bufsz > 0);  
         assert(in->file->name);  
   
         if (-1 == (ssz = read(in->file->fd, in->buf, in->bufsz)))  
                 warn("%s", in->file->name);  
         else  
                 (void)printf("%s: filled %zd bytes\n",  
                                 in->file->name, ssz);  
   
         return(ssz);  
 }  
   
   
 static int  
 md_run(struct md_buf *out, struct md_buf *in)  
 {  
         struct md_mbuf   mbuf;  
         ssize_t          sz, i;  
         char             line[BUFSIZ];  
         size_t           pos;  
   
         assert(in);  
         assert(out);  
   
         mbuf.buf = out;  
         mbuf.pos = 0;  
   
         /* LINTED */  
         for (pos = 0; ; ) {  
                 if (-1 == (sz = md_buf_fill(in)))  
                         return(1);  
                 else if (0 == sz)  
                         break;  
   
                 for (i = 0; i < sz; i++) {  
                         if ('\n' == in->buf[i]) {  
                                 if (md_line(&mbuf, in, line, pos))  
                                         return(1);  
                                 in->line++;  
                                 pos = 0;  
                                 continue;  
                         }  
   
                         if (pos < BUFSIZ) {  
                                 /* LINTED */  
                                 line[pos++] = in->buf[i];  
                                 continue;  
                         }  
   
                         warnx("%s: line %zu too long",  
                                         in->file->name, in->line);  
                         return(1);  
                 }  
         }  
   
         if (0 != pos && md_line(&mbuf, in, line, pos))  
                 return(1);  
   
         return(md_buf_flush(&mbuf) ? 0 : 1);  
 }  
   
   
 static int  
 md_buf_flush(struct md_mbuf *buf)  
 {  
         ssize_t          sz;  
   
         assert(buf);  
         assert(buf->buf);  
         assert(buf->buf->file);  
         assert(buf->buf->buf);  
         assert(buf->buf->file->name);  
   
         (void)printf("%s: flushing %zu bytes\n",  
                         buf->buf->file->name, buf->pos);  
   
         if (0 == buf->pos)  
                 return(1);  
   
         sz = write(buf->buf->file->fd, buf->buf->buf, buf->pos);  
   
         if (-1 == sz) {  
                 warn("%s", buf->buf->file->name);  
                 return(0);  
         } else if ((size_t)sz != buf->pos) {  
                 warnx("%s: short write", buf->buf->file->name);  
                 return(0);  
         }  
   
         buf->pos = 0;  
         return(1);  
 }  
   
   
 static int  
 md_buf_putchar(struct md_mbuf *buf, char c)  
 {  
         return(md_buf_puts(buf, &c, 1));  
 }  
   
   
 static int  
 md_buf_puts(struct md_mbuf *buf, const char *p, size_t sz)  
 {  
         size_t           ssz;  
   
         assert(p);  
         assert(buf);  
         assert(buf->buf);  
   
         while (buf->pos + sz > buf->buf->bufsz) {  
                 ssz = buf->buf->bufsz - buf->pos;  
                 (void)memcpy(buf->buf->buf + buf->pos, p, ssz);  
                 p += ssz;  
                 sz -= ssz;  
                 buf->pos += ssz;  
   
                 if ( ! md_buf_flush(buf))  
                         return(0);  
         }  
   
         (void)memcpy(buf->buf->buf + buf->pos, p, sz);  
         buf->pos += sz;  
         return(1);  
 }  
   
   
 static int  
 md_line(struct md_mbuf *out, const struct md_buf *in,  
                 const char *buf, size_t sz)  
 {  
   
         assert(buf);  
         assert(out);  
         assert(in);  
   
         if ( ! md_buf_puts(out, buf, sz))  
                 return(1);  
         if ( ! md_buf_putchar(out, '\n'))  
                 return(1);  
   
         return(0);  
 }  
   
   
 static void  static void
 usage(void)  usage(void)
 {  {
         extern char     *__progname;          extern char     *__progname;
   
         (void)printf("usage: %s [-o outfile] infile\n", __progname);          (void)fprintf(stderr, "usage: %s [-v] [-Wwarn...]  "
                           "[-f filter] [-o outfile] [infile]\n",
                           __progname);
 }  }
   

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

CVSweb