home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / word2x0a.zip / source / word2x.cc < prev    next >
C/C++ Source or Header  |  1998-04-20  |  7KB  |  387 lines

  1. /* $Id: word2x.cc,v 1.12 1997/04/13 05:53:11 dps Exp $ */
  2. #ifdef __GNUC__
  3. #define alloca __builtin_alloca
  4. #else
  5. #if HAVE_ALLOCA_H
  6. #include <alloca.h>
  7. #else /* Do not have alloca.h */
  8. #ifdef _AIX
  9.  #pragma alloca
  10. #else /* not _AIX */
  11. char *alloca();
  12. #endif /* _AIX */
  13. #endif /* HAVE_ALLOCA_H */
  14. #endif /* __GNUC__ */
  15.  
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #ifdef HAVE_STRING_H
  19. #include <string.h>
  20. #else
  21. #include <strings.h>
  22. #endif /* HAVE_STRING_H */
  23. #include <time.h>
  24. #include "getopt.h"
  25. #include <ctype.h>
  26. #include "interface.h"
  27. #include "lib.h"
  28. #include "config.h"
  29.  
  30. #ifndef N
  31. #define N(x) (sizeof(x)/sizeof(x[0]))
  32. #endif
  33.  
  34. extern docfmt txtfmt, latexfmt, htmlfmt;
  35.  
  36. /* postfix test */
  37. static int postfix(const char *s, const char *t)
  38. {
  39.     unsigned int n;
  40.  
  41.     n=strlen(t);
  42.     if (strlen(s)<=n)
  43.     return 0;
  44.     return (strcasecmp(s+strlen(s)-n, t)==0) ? 1 : 0;
  45. }
  46.  
  47. /*
  48.  * open file with .doc or .DOC tacked on the end if the filename alone
  49.  * does not exist
  50.  */
  51. static FILE *open_file(const char *f)
  52. {
  53.     char *s;
  54.     FILE *r;
  55.  
  56.     if ((r=fopen(f, "r"))!=NULL)
  57.     return r;
  58.  
  59.     if ((s=(char *) malloc(strlen(f)+4))==NULL)
  60.     {
  61.     fprintf(stderr,"word2x: skipping %s due to malloc failure\n", f);
  62.     return NULL;
  63.     }
  64.     strcpy(s, f);
  65.     strcat(s, ".doc");
  66.  
  67.     if ((r=fopen(s, "r"))==NULL)
  68.     {
  69.     free(s);
  70.     return r;
  71.     }
  72.     
  73.     strcpy(s+strlen(f), ".DOC");
  74.     r=fopen(s, "r");
  75.     free(s);
  76.  
  77.     return r;
  78. }
  79.  
  80.  
  81. /* Just read the files and pass the results on... */
  82. static void convert(FILE *f, FILE *out, const struct docfmt *fmt)
  83. {
  84.     const tok_seq::tok *d;
  85.     int i;
  86.     void *dptr;
  87.     tok_seq rd(f);
  88.  
  89.     dptr=fmt->new_state();
  90.     while ((d=rd.read_token())!=NULL)
  91.     {
  92.     i=d->tok;
  93.  
  94. #ifndef C_ALLOCA
  95.     alloca(0);
  96. #endif
  97.  
  98.     if (i<NFUNCS && d->end==tok_seq::tok::TOK_START)
  99.     {
  100.         (fmt->f[i]).start(d, fmt, out, dptr);
  101.     }
  102.     else
  103.     {
  104.         (fmt->f[i]).end(d, fmt, out, dptr);
  105.     }
  106.     }
  107.     fmt->free_state(dptr);
  108. }
  109.  
  110. static const char *outname(const char *in, const char *ext)
  111. {
  112.     char *r, *s;
  113.     int adj;
  114.  
  115.     if (postfix(in, ".doc"))
  116.     adj=4;
  117.     else
  118.     adj=0;
  119.  
  120.     if ((r=(char *) malloc(strlen(in)+strlen(ext)-adj+1))==NULL)
  121.     return NULL;
  122.     strcpy(r, in);
  123.     s=r+strlen(r)-adj;
  124.     strcpy(s, ext);
  125.  
  126.     return r;
  127. }
  128.  
  129. int main(int argc, const char **argv)
  130. {
  131.     static const struct
  132.     {
  133.     const char *name;
  134.     char *(*fmt)(time_t);
  135.     } dates[]=
  136.     {
  137.     { "uk", uk_date },
  138.     { "british", uk_date },
  139.     { "us", us_date },
  140.     };
  141.     static const struct
  142.     {
  143.     const char *name;
  144.     const char *ext;
  145.     const docfmt *fmt;
  146.     } formats[]=
  147.     {
  148.     { "text", ".txt", &txtfmt },
  149.     { "latex", ".tex", &latexfmt },
  150.     { "html", ".html", &htmlfmt },
  151.     };
  152. #if !defined(NO_LONG_OPTS)
  153.     static const struct option lopts[]=
  154.     {
  155.     { "version", 0, NULL, 'V' },
  156.     { "help", 0, NULL, 'h' },
  157.     { "format", 1, NULL, 'f' },
  158.     { "width", 0, NULL,  'w' },
  159.     { "dates", 0, NULL, 'd' },
  160.     { "verbose", 0, NULL, 'v' },
  161.     { "quiet", 0, NULL, 'q' },
  162.     { "pagebreak", 0, NULL, 'p' },
  163.     };
  164. #endif
  165.  
  166.     char *(*dfmt)(time_t);
  167.     FILE *in, *out;
  168.     docfmt fmt;
  169.     int c, i, opt_index, n, wd;
  170.     const char *s,*t, *ext;
  171.     int verbose=0, name_alloced, res;
  172.  
  173.     struct
  174.     {
  175.     unsigned new_pages:1;
  176.     } flags={ 0 };
  177.     res=0;            // Return code 0
  178.     fmt=*(formats[0].fmt);    // Set default format
  179.     dfmt=dates[0].fmt;        // Set default date format
  180.     wd=fmt.maxline;        // Set default width
  181.     ext=formats[0].ext;        // Set default extension
  182.  
  183.     while ((c=getopt_long(argc, (char *const *) argv, "Vhpvqf:w:d:",
  184.               lopts, &opt_index))!=-1)
  185.     {
  186.     switch(c)
  187.     {
  188.     case 'V':            // Print version and exit
  189.         fputs("word2x 0.001\n", stderr);
  190.         return 0;
  191.  
  192.     case 'p':
  193.         flags.new_pages=1;
  194.         break;
  195.  
  196.     case 'h':            // Help
  197.         fputs("Usage: word2x [-f <output format>] [-dates <date format>]"
  198.           " [-w <line length>]\n"
  199.           "              <infile> [<outfile>]\n"
  200.           "Supported date formats: ", stderr);
  201.         for (i=0; i<(int) N(dates); i++)
  202.         {
  203.         if (i!=0)
  204.             fputs(", ", stderr);
  205.         fputs(dates[i].name, stderr);
  206.         }
  207.         fputs("\nSupported output formats: ", stderr);
  208.         for (i=0; i<(int) N(formats); i++)
  209.         {
  210.         if (i!=0)
  211.             fputs(", ", stderr);
  212.         fputs(formats[i].name, stderr);
  213.         }
  214.         fputc('\n', stderr);
  215.         return 0;
  216.         
  217.     case 'v':            // Verbose mode
  218.         verbose=1;
  219.         break;
  220.         
  221.     case 'q':            // Queit mode
  222.         verbose=0;
  223.         break;
  224.         
  225.     case 'w':            // Width
  226.         n=0;
  227.         if (*optarg=='\0')
  228.         {
  229.         fputs("-w requires a number\n", stderr);
  230.         break;
  231.         }
  232.         for (s=optarg; *s; s++)
  233.         {
  234.         if (!isdigit(*s))
  235.         {
  236.             res=1;
  237.             fputs("-w requires a number\n", stderr);
  238.             break;
  239.         }
  240.         n=n*10+(*s-'0');
  241.         }
  242.         if (*s=='\0')
  243.         wd=n;
  244.         break;
  245.         
  246.     case 'd':            // Date format
  247.         for (n=-1, i=0; i<(int) N(dates); i++)
  248.         {
  249.         if (strcasecmp(dates[i].name, optarg)==0)
  250.         {
  251.             n=i;
  252.             break;
  253.         }
  254.         }
  255.         if (n==-1)
  256.         {
  257.         res=1;
  258.         fprintf(stderr, "%s is not a known date format\n", optarg);
  259.         }
  260.         else
  261.         dfmt=dates[i].fmt;
  262.         break;
  263.         
  264.     case 'f':            // Output format
  265.         for (n=-1, i=0; i<(int) N(formats); i++)
  266.         {
  267.         if (strcasecmp(formats[i].name, optarg)==0)
  268.         {
  269.             n=i;
  270.             break;
  271.         }
  272.         }
  273.         if (n==-1)
  274.         {
  275.         res=1;
  276.         fprintf(stderr, "%s is not a known output format\n", optarg);
  277.         }
  278.         else
  279.         {
  280.         fmt=*(formats[i].fmt);
  281.         ext=formats[i].ext;
  282.         }
  283.         break;
  284.         
  285.     case '?':
  286.         break;
  287.         
  288.     default:
  289.         abort();
  290.     }
  291.     }
  292.  
  293.     /* Make sure we have a filename */
  294.     if (optind==argc)
  295.     {
  296.     fputs("word2x: filename required (can not handle stdin)\n", stderr);
  297.     return 1;
  298.     }
  299.  
  300.     /* Stop if invalid switches */
  301.     if (res!=0)
  302.     return res;
  303.  
  304.     /* Set line width and date format */
  305.     fmt.date=dfmt;
  306.     fmt.maxline=wd;
  307.     fmt.flags.new_pages=flags.new_pages;
  308.  
  309.     /* Loop through files */
  310.     for (i=optind; i<argc; i++)
  311.     {
  312.     s=argv[i];
  313.     if (i==argc-1 || postfix(argv[i+1],".doc"))
  314.     {
  315.         /* Generate output file name */
  316.         if ((t=outname(argv[i], ext))==NULL)
  317.         {
  318.         fprintf(stderr,
  319.             "word2x: skipping %s due to allocation failure\n",
  320.             s);
  321.         continue;
  322.         }
  323.         name_alloced=1;
  324.     }
  325.     else
  326.     {
  327.         t=argv[++i];
  328.         name_alloced=0;
  329.     }
  330.  
  331.     /* Open input file */
  332.     if ((in=open_file(s))==NULL)
  333.     {
  334.         if (name_alloced)
  335.         free((void *) t);
  336.         fprintf(stderr, "Could not open %s\n", s);
  337.         res=1;
  338.         continue;
  339.     }
  340.  
  341.     /* Check seekability of in file */
  342.     if (fseek(in, 0L, SEEK_SET)!=0)
  343.     {
  344.         fprintf(stderr, "word2x: %s is not seekable\n", s);
  345.         fclose(in);
  346.         res=1;
  347.         continue;
  348.     }
  349.  
  350.     /* Open output file */
  351.     if (strcmp(t,"-")==0)
  352.     {
  353.         out=stdout;
  354.         t="standard output";
  355.     }
  356.     else
  357.     {
  358.         if ((out=fopen(t, "w"))==NULL)
  359.         {
  360.         fprintf(stderr, "Could not open %s\n", t);
  361.         if (name_alloced)
  362.             free((void *) t);
  363.         fclose(in);
  364.         res=1;
  365.         continue;
  366.         }
  367.     }
  368.  
  369.     /* Finally do something */
  370.     if (verbose)
  371.         fprintf(stderr, "Converting %s to %s\n", s, t);
  372.     convert(in, out, &fmt);
  373.     fclose(in);
  374.     if (out!=stdout)
  375.         fclose(out);
  376.     }
  377.  
  378.     return res;
  379. }
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.