Back to index

tetex-bin  3.0
mpto.c
Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright 1990 - 1995 by AT&T Bell Laboratories.
00003 
00004 Permission to use, copy, modify, and distribute this software
00005 and its documentation for any purpose and without fee is hereby
00006 granted, provided that the above copyright notice appear in all
00007 copies and that both that the copyright notice and this
00008 permission notice and warranty disclaimer appear in supporting
00009 documentation, and that the names of AT&T Bell Laboratories or
00010 any of its entities not be used in advertising or publicity
00011 pertaining to distribution of the software without specific,
00012 written prior permission.
00013 
00014 AT&T disclaims all warranties with regard to this software,
00015 including all implied warranties of merchantability and fitness.
00016 In no event shall AT&T be liable for any special, indirect or
00017 consequential damages or any damages whatsoever resulting from
00018 loss of use, data or profits, whether in an action of contract,
00019 negligence or other tortious action, arising out of or in
00020 connection with the use or performance of this software.
00021 ****************************************************************/
00022 
00023 /* This program transforms a MetaPost input file into a TeX or LaTeX input
00024  * file by stripping out btex...etex and verbatimtex...etex sections.
00025  * Leading and trailing spaces and tabs are removed from the extracted
00026  * material and it is surrounded by the preceding and following strings
00027  * defined immediately below.  The input file should be given as argument 1
00028  * and the resulting TeX file is written on standard output.
00029  */
00030 
00031 /* Or we translate to troff.  Just a matter of different boilerplate.  */
00032 
00033 #include "c-auto.h"  /* For WEB2CVERSION */
00034 #include "cpascal.h"
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <kpathsea/config.h>
00038 #include <kpathsea/variable.h>
00039 
00040 #ifdef WIN32
00041 #include <string.h>
00042 #endif
00043 
00044 
00045 /* MetaPost itself has a configurable max line length, copy the limits
00046    from mp.ch */
00047 #define INF_BUF_SIZE  500
00048 #define SUP_BUF_SIZE  300000
00049 #define BUF_SIZE_NAME "buf_size"
00050 
00051 char*  tex_predoc = "";
00052 char*  tex_postdoc = "\\end{document}\n";
00053 char*  tex_pretex1 = "\\shipout\\hbox{\\smash{\\hbox{\\hbox{%% line %d %s\n";
00054 char*  tex_pretex = "\\shipout\\hbox{\\smash{\\hbox{\\hbox{%% line %d %s\n";
00055 char*  tex_posttex = "}\\vrule width1sp}}}\n";
00056 char*  tex_preverb1 = "";                 /* if very first instance */
00057 char*  tex_preverb = "%% line %d %s\n";   /* all other instances */
00058 char*  tex_postverb = "%\n";
00059 
00060 /* According to CSTR #54 the ".lf" directive should be ".lf %d %s",
00061  * not ".lf line %d %s" as used in the original code.  This affects
00062  * troff_pretex1, troff_pretex, troff_preverb1, troff_preverb.
00063  */
00064 char*  troff_predoc = ".po 0\n";
00065 char*  troff_postdoc = "";
00066 char*  troff_pretex1 = ".lf %d %s\n";     /* first instance */
00067 char*  troff_pretex = ".bp\n.lf %d %s\n"; /* subsequent instances */
00068 char*  troff_posttex = "\n";
00069 char*  troff_preverb1 = ".lf %d %s\n";
00070 char*  troff_preverb = ".lf %d %s\n";
00071 char*  troff_postverb = "\n";
00072 
00073 char*  predoc;
00074 char*  postdoc;
00075 char*  pretex1;
00076 char*  pretex;
00077 char*  posttex;
00078 char*  preverb1;
00079 char*  preverb;
00080 char*  postverb;
00081 
00082 char *mpname;
00083 FILE *mpfile;
00084 int lnno = 0;        /* current line number */
00085 int texcnt = 0;             /* btex..etex blocks so far */
00086 int verbcnt = 0;     /* verbatimtex..etex blocks so far */
00087 char *buf;           /* the input line */
00088 long bufsize = 0;       /* the buffer size */
00089 char *bb, *tt, *aa;  /* start of before, token, and after strings */
00090 
00091 void err P1C(char *, msg)
00092 {
00093        fprintf(stderr, "mpto: %s:%d: %s\n",
00094               mpname, lnno, msg);
00095        exit(1);
00096 }
00097 
00098 char *getline()      /* returns NULL on EOF or error, otherwise buf */
00099 {
00100        int c;
00101        unsigned loc = 0;
00102        while ((c = getc (mpfile)) != EOF && c != '\n' && c != '\r') {
00103               buf[loc++] = c;
00104               if (loc == bufsize)
00105                      err("Line is too long");
00106        }
00107        if (c == EOF) return NULL;
00108        buf[loc] = 0;
00109        if (c == '\r') {
00110               c = getc(mpfile);
00111               if (c != '\n') ungetc(c, mpfile);
00112        }
00113        lnno++;
00114        return buf;
00115 }
00116 
00117 
00118 /* Return nonzero if a prefix of string s matches the null-terminated string t
00119  * and the next character is not a letter of an underscore.
00120  */
00121 int match_str P2C(char*, s, char *, t)
00122 {
00123        while (*t!=0) {
00124               if (*s!=*t) return 0;
00125               s++; t++;
00126        }
00127        switch (*s) {
00128        case 'a': case 'c': case 'd': case 'f': case 'g': case 'h':
00129        case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
00130        case 'o': case 'p': case 'q': case 'r': case 's': case 't':
00131        case 'u': case 'w': case 'x': case 'y': case 'z': case '_':
00132        case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00133        case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
00134        case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00135        case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00136        case 'Y': case 'Z': case 'b': case 'e': case 'v':
00137               return 0;
00138        default:
00139               return 1;
00140        }
00141 }
00142 
00143 
00144 /* This function tries to express s as the concatenation of three strings
00145  * b, t, a, with the global pointers bb, tt, and aa set to the start of the
00146  * corresponding strings.  String t is either a quote mark, a percent sign,
00147  * or an alphabetic token "btex", "etex", or "verbatimtex".  (An alphabetic
00148  * token is a maximal sequence of letters and underscores.)  If there are
00149  * several possible substrings t, we choose the leftmost one.  If there is
00150  * no such t, we set b=s and return 0.
00151  */
00152 int getbta P1C(char *, s)
00153 {
00154        int ok=1;     /* zero if last character was a-z, A-Z, or _ */
00155 
00156        bb = s;
00157        for (tt=bb; *tt!=0; tt++)
00158               switch (*tt) {
00159               case '"': case '%':
00160                      aa = tt+1;
00161                      return 1;
00162               case 'b':
00163                      if (ok && match_str(tt,"btex")) {
00164                             aa = tt+4;
00165                             return 1;
00166                      } else ok=0;
00167                      break;
00168               case 'e':
00169                      if (ok && match_str(tt,"etex")) {
00170                             aa = tt+4;
00171                             return 1;
00172                      } else ok=0;
00173                      break;
00174               case 'v':
00175                      if (ok && match_str(tt,"verbatimtex")) {
00176                             aa = tt+11;
00177                             return 1;
00178                      } else ok=0;
00179                      break;
00180               case 'a': case 'c': case 'd': case 'f': case 'g': case 'h':
00181               case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
00182               case 'o': case 'p': case 'q': case 'r': case 's': case 't':
00183               case 'u': case 'w': case 'x': case 'y': case 'z': case '_':
00184               case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00185               case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
00186               case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
00187               case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
00188               case 'Y': case 'Z':
00189                      ok = 0;
00190                      break;
00191               default:
00192                      ok = 1;
00193               }
00194        aa = tt;
00195        return 0;
00196 }
00197 
00198 
00199 void copytex()
00200 {
00201        char *s;      /* where a string to print stops */
00202        char c;
00203 
00204        while (*aa==' ' || *aa=='\t') aa++;
00205        if (*aa==0)
00206               if ((aa=getline())==NULL)
00207                      err("btex section does not end");
00208        do {   if (*aa==0)
00209                      if ((aa=getline())==NULL)
00210                             err("btex section does not end");
00211                      else printf("\n");
00212               if (getbta(aa) && *tt=='e') {
00213                      s = tt-1;
00214                      while (s>=bb && (*s==' ' || *s=='\t'))
00215                             s--;
00216                      s++;
00217               } else {
00218                      if (*tt=='b') err("btex in TeX mode");
00219                      if (*tt=='v') err("verbatimtex in TeX mode");
00220                      s = aa;
00221               }
00222               c = *s;
00223               *s = 0;
00224               printf("%s", bb);
00225               *s = c;
00226        } while (*tt!='e');
00227 }
00228 
00229 
00230 void do_line()
00231 {
00232        aa = buf;
00233        while (getbta(aa))
00234               if (*tt=='%') break;
00235               else if (*tt=='"') {
00236                      do if (!getbta(aa)) err("string does not end");
00237                      while (*tt!='"');
00238               } else if (*tt=='b') {
00239                      if (texcnt++ ==0) printf(pretex1,lnno,mpname);
00240                      else printf(pretex,lnno,mpname);
00241                      copytex();
00242                      printf("%s",posttex);
00243               } else if (*tt=='v') {
00244                      if (verbcnt++ ==0 && texcnt==0)
00245                             printf(preverb1,lnno,mpname);
00246                      else printf(preverb,lnno,mpname);
00247                      copytex();
00248                      printf("%s",postverb);
00249               } else err("unmatched etex");
00250 }
00251 
00252 static const_string MPTOHELP[] = {
00253     "Usage: mpto [-tex|-troff] MPFILE",
00254     "  Strip btex..etex and verbatimtex...etex parts from MetaPost input",
00255     "  file MPFILE, converting to either TeX or troff (TeX by default).",
00256     "",
00257     "--help      display this help and exit",
00258     "--version   output version information and exit",
00259 #ifdef AMIGA
00260     "-E <errlog-file>",
00261 #endif
00262     NULL
00263 };
00264   
00265 int main P2C(int, argc, char **, argv)
00266 {
00267         int mode;
00268         char *buf_size_str;
00269         
00270         kpse_set_program_name(argv[0], NULL);
00271        
00272        if (argc == 1) {
00273          fputs ("mpto: Need exactly one file argument.\n", stderr);
00274          fputs ("Try `mpto --help' for more information.\n", stderr);
00275          exit(1);
00276        } else if (argc > 1 && strcmp (argv[1], "--help") == 0) {
00277             usagehelp (MPTOHELP, NULL);
00278        } else if (argc > 1 && strcmp (argv[1], "--version") == 0) {
00279           printf ("mpto%s 0.63\n\
00280 Copyright (C) 1996 AT&T Bell Laboratories.\n\
00281 There is NO warranty.  You may redistribute this software\n\
00282 under the terms of the GNU General Public License\n\
00283 and the mpto copyright.\n\
00284 For more information about these matters, see the files\n\
00285 named COPYING and the mpto source.\n\
00286 Primary author of mpto: John Hobby.\n",
00287 WEB2CVERSION);
00288          exit (0);
00289        } else if (argc == 2) {
00290          mpname = argv[1];
00291          mode = 0;
00292 #ifdef AMIGA
00293        } else if (argc == 3) {
00294          if (strcmp (argv[1], "-tex") == 0) {
00295            mpname = argv[2];
00296            mode = 0;
00297          } else if (strcmp (argv[1], "-troff") == 0) {
00298            mpname = argv[2];
00299            mode = 1;
00300          } else if (strncmp(argv[2], "-E", 2) || (argv[2]+2 == NULL)) {
00301            usage(argv[0]);
00302          } else {
00303            mpname = argv[1];
00304            freopen(argv[2]+2, "w", stderr);
00305          }
00306        } else if (argc == 4) {
00307          if (strcmp (argv[1], "-tex") == 0) {
00308            mode = 0;
00309          } else if (strcmp (argv[1], "-troff") == 0) {
00310            mode = 1;
00311          } else {
00312            usage(argv[0]);
00313          }
00314          if (strncmp(argv[3], "-E", 2) || (argv[3]+2 == NULL)) {
00315            usage(argv[0]);
00316          } else {
00317            mpname = argv[2];
00318            freopen(argv[3]+2, "w", stderr);
00319          }
00320        } else {
00321          usage(argv[0]);
00322        }
00323 #else /* not AMIGA */
00324        } else if (argc == 3) {
00325          if (strcmp (argv[1], "-tex") == 0) {
00326            mode = 0;
00327          } else if (strcmp (argv[1], "-troff") == 0) {
00328            mode = 1;
00329          } else {
00330            usage (argv[0]);
00331          }
00332          mpname = argv[2];
00333        } else {
00334          usage(argv[0]);
00335        }
00336 #endif /* not AMIGA */
00337        mpfile = fopen(mpname, "r");
00338        if (mpfile==NULL) {
00339          fprintf (stderr, "%s: ", argv[0]);
00340          perror (mpname);
00341          exit (1);
00342        }
00343 
00344         buf_size_str = kpse_var_value(BUF_SIZE_NAME);
00345         if (buf_size_str)
00346            bufsize = atoi(buf_size_str);
00347         if (bufsize < INF_BUF_SIZE)
00348            bufsize = INF_BUF_SIZE;
00349         if (bufsize > SUP_BUF_SIZE)
00350            bufsize = SUP_BUF_SIZE;
00351         buf = (char*)xmalloc(bufsize);
00352         if (buf_size_str) free(buf_size_str);
00353 
00354        /* This is far from elegant, but life is short.  */
00355        if (mode == 0) {
00356           predoc = tex_predoc;
00357           postdoc = tex_postdoc;
00358           pretex1 = tex_pretex1;
00359           pretex = tex_pretex;
00360           posttex = tex_posttex;
00361           preverb1 = tex_preverb1;
00362           preverb = tex_preverb;
00363           postverb = tex_postverb;
00364        } else {
00365           predoc = troff_predoc;
00366           postdoc = troff_postdoc;
00367           pretex1 = troff_pretex1;
00368           pretex = troff_pretex;
00369           posttex = troff_posttex;
00370           preverb1 = troff_preverb1;
00371           preverb = troff_preverb;
00372           postverb = troff_postverb;
00373        }
00374        printf("%s",predoc);
00375        while (getline()!=NULL)
00376               do_line();
00377        printf("%s",postdoc);
00378         free(buf);
00379        exit(0);
00380 }