home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / text / tex / detex.l (.txt) < prev    next >
LaTeX Document  |  1995-02-27  |  17KB  |  480 lines

  1. #ifndef lint
  2. static char    rcsid[] = "$Header: /usr/src/local/bin/detex/RCS/detex.l,v 2.16 1993/01/14 16:48:25 trinkle Exp $";
  3. #endif
  4.  * detex [-e environment-list] [-c] [-l] [-n] [-s] [-t] [-w] [file[.tex]]
  5.  *    This program is used to remove TeX or LaTeX constructs from a text
  6.  *    file.
  7.  * Written by:
  8.  *    Daniel Trinkle
  9.  *    Department of Computer Science
  10.  *    Purdue University
  11. #ifdef _DCC
  12. #include <string.h>
  13. #define index    strchr
  14. #define rindex    strrchr
  15. #endif /* _DCC */
  16. #include "detex.h"
  17. #ifdef USG
  18. #include <string.h>
  19. #define index    strchr
  20. #define rindex    strrchr
  21. #else
  22. #include <strings.h>
  23. #endif
  24. #ifndef MAXPATHLEN
  25. #include <sys/param.h>
  26. #endif
  27. #define LaBEGIN     if (fLatex) BEGIN
  28. #define CITEBEGIN    if (fLatex && !fCite) BEGIN
  29. #define IGNORE        if (fSpace && !fWord) putchar(' ')
  30. #define SPACE        if (!fWord) putchar(' ')
  31. #define NEWLINE     if (!fWord) putchar('\n')
  32. #ifndef NO_MALLOC_DECL
  33. char    *malloc();
  34. #endif
  35. char    *rgsbEnvIgnore[MAXENVS];    /* list of environments ignored */
  36. char    *rgsbIncList[MAXINCLIST];    /* list of includeonly files */
  37. char    *rgsbInputPaths[MAXINPUTPATHS]; /* list of input paths in order */
  38. char    sbCurrentEnv[CCHMAXENV];    /* current environment being ignored */
  39. char    *sbProgName;            /* name we were invoked with */
  40. FILE    *rgfp[NOFILE+1];        /* stack of input/include files */
  41. int    cfp = 0;            /* count of files in stack */
  42. int    cOpenBrace = 0;         /* count of `{' in <LaMacro2> */
  43. int    csbEnvIgnore;            /* count of environments ignored */
  44. int    csbIncList = 0;         /* count of includeonly files */
  45. int    csbInputPaths;            /* count of input paths */
  46. int    fLatex = 0;            /* flag to indicated delatex */
  47. int    fWord = 0;            /* flag for -w option */
  48. int    fFollow = 1;            /* flag to follow input/include */
  49. int    fCite = 0;            /* flag to echo \cite and \ref args */
  50. int    fSpace = 0;            /* flag to replace \cs with space */
  51. int    fForcetex = 0;            /* flag to inhibit latex mode */
  52. S    [ \t\n]*
  53. W    [a-zA-Z]+
  54. %Start Define Display IncludeOnly Input Math Normal Control
  55. %Start LaBegin LaDisplay LaEnd LaEnv LaFormula LaInclude
  56. %Start LaMacro LaMacro2 LaVerbatim
  57. <Normal>"%".*           /* ignore comments */   ;
  58. <Normal>"\\begin"{S}"{"{S}"document"{S}"}"      {fLatex = !fForcetex; IGNORE;}
  59. <Normal>"\\begin"     /* environment start */   {LaBEGIN LaBegin; IGNORE;}
  60. <LaBegin>{S}"{"{S}"verbatim"{S}"}"              {   if (BeginEnv("verbatim"))
  61.                             BEGIN LaEnv;
  62.                             else
  63.                             BEGIN LaVerbatim;
  64.                             IGNORE;
  65.                         }
  66. <LaVerbatim>"\\end"{S}"{"{S}"verbatim"{S}"}" /* verbatim mode */
  67.                         {BEGIN Normal; IGNORE;}
  68. <LaVerbatim>.                    ECHO;
  69. <LaBegin>{W}                    {   if (BeginEnv(yytext))
  70.                             BEGIN LaEnv;
  71.                             else
  72.                             BEGIN LaMacro;
  73.                             IGNORE;
  74.                         }
  75. <LaBegin>"\n"                                   NEWLINE;
  76. <LaBegin>.                    ;
  77. <LaEnv>"\\end"  /* absorb some environments */  {LaBEGIN LaEnd; IGNORE;}
  78. <LaEnv>"\n"                                     NEWLINE;
  79. <LaEnv>.                    ;
  80. <LaEnd>{W}         /* end environment */    {   if (EndEnv(yytext))
  81.                             BEGIN Normal;
  82.                             IGNORE;
  83.                         }
  84. <LaEnd>"}"                                      {BEGIN LaEnv; IGNORE;}
  85. <LaEnd>"\n"                                     NEWLINE;
  86. <LaEnd>.                    ;
  87. <Normal>"\\bibitem"         /* ignore args  */  {LaBEGIN LaMacro2; IGNORE;}
  88. <Normal>"\\bibliography"    /* of these \cs */  {LaBEGIN LaMacro; IGNORE;}
  89. <Normal>"\\bibstyle"                            {LaBEGIN LaMacro; IGNORE;}
  90. <Normal>"\\cite"                                {CITEBEGIN LaMacro2; IGNORE;}
  91. <Normal>"\\documentstyle"                       {LaBEGIN LaMacro; IGNORE;}
  92. <Normal>"\\end"                                 {LaBEGIN LaMacro; IGNORE;}
  93. <Normal>"\\index"                               {LaBEGIN LaMacro2; SPACE;}
  94. <Normal>"\\label"                               {LaBEGIN LaMacro; IGNORE;}
  95. <Normal>"\\pageref"                             {CITEBEGIN LaMacro; IGNORE;}
  96. <Normal>"\\pagestyle"                           {LaBEGIN LaMacro; IGNORE;}
  97. <Normal>"\\ref"                                 {CITEBEGIN LaMacro; IGNORE;}
  98. <Normal>"\\setcounter"                          {LaBEGIN LaMacro; IGNORE;}
  99. <Normal>"\\verb" /* ignore \verb<char>...<char> */
  100.                         {   if (fLatex) {
  101.                             char verbchar, c;
  102.                             verbchar = input();
  103.                             while ((c = input()) != verbchar)
  104.                                 if (c == '\n')
  105.                                 NEWLINE;
  106.                             }
  107.                             IGNORE;
  108.                         }
  109. <LaMacro>"}"                                    BEGIN Normal;
  110. <LaMacro>"\n"                                   NEWLINE;
  111. <LaMacro>.                    ;
  112. <LaMacro2>"{"                                   {   cOpenBrace++; }
  113. <LaMacro2>"}"                                   {   cOpenBrace--;
  114.                             if (cOpenBrace == 0)
  115.                             BEGIN Normal;
  116.                         }
  117. <LaMacro2>"\n"                                  NEWLINE;
  118. <LaMacro2>.                    ;
  119. <Normal>"\\def"         /* ignore def begin */  {BEGIN Define; IGNORE;}
  120. <Define>"{"                                     BEGIN Normal;
  121. <Define>"\n"                                    NEWLINE;
  122. <Define>.                    ;
  123. <Normal>"\\("           /* formula mode */      {LaBEGIN LaFormula; IGNORE;}
  124. <LaFormula>"\\)"                                BEGIN Normal;
  125. <LaFormula>"\n"                                 NEWLINE;
  126. <LaFormula>.                    ;
  127. <Normal>"\\["           /* display mode */      {LaBEGIN LaDisplay; IGNORE;}
  128. <LaDisplay>"\\]"                                BEGIN Normal;
  129. <LaDisplay>"\n"                                 NEWLINE;
  130. <LaDisplay>.                    ;
  131. <Normal>"$$"            /* display mode */      {BEGIN Display; IGNORE;}
  132. <Display>"$$"                                   BEGIN Normal;
  133. <Display>"\n"                                   NEWLINE;
  134. <Display>.                    ;
  135. <Normal>"$"             /* math mode */         {BEGIN Math; IGNORE;}
  136. <Math>"$"                                       BEGIN Normal;
  137. <Math>"\n"                                      NEWLINE;
  138. <Math>"\\$"                                     ;
  139. <Math>.                     ;
  140. <Normal>"\\include"     /* process files */     {LaBEGIN LaInclude; IGNORE;}
  141. <LaInclude>[^{ \t\n}]+                {   IncludeFile(yytext);
  142.                             BEGIN Normal;
  143.                         }
  144. <LaInclude>"\n"                                 NEWLINE;
  145. <LaInclude>.                    ;
  146. <Normal>"\\includeonly"                         {BEGIN IncludeOnly; IGNORE;}
  147. <IncludeOnly>[^{ \t,\n}]+            AddInclude(yytext);
  148. <IncludeOnly>"}"                                {   if (csbIncList == 0)
  149.                             rgsbIncList[csbIncList++] = '\0';
  150.                             BEGIN Normal;
  151.                         }
  152. <IncludeOnly>"\n"                               NEWLINE;
  153. <IncludeOnly>.                    ;
  154. <Normal>"\\input"                               {BEGIN Input; IGNORE;}
  155. <Input>[^{ \t\n}]+                {   InputFile(yytext);
  156.                             BEGIN Normal;
  157.                         }
  158. <Input>"\n"                                     NEWLINE;
  159. <Input>.                    ;
  160. <Normal>\\(aa|AA|ae|AE|oe|OE|ss)[ \t]*[ \t\n}] /* handle ligatures */
  161.                         {printf("%.2s", yytext+1);}
  162. <Normal>\\[OoijLl][ \t]*[ \t\n}]        {printf("%.1s", yytext+1);}
  163. <Normal>\\[a-zA-Z@]+    /* ignore other \cs */    {BEGIN Control; IGNORE;}
  164. <Normal>"\\ "                                   SPACE;
  165. <Normal>\\.                    IGNORE;
  166. <Control>\\[a-zA-Z@]+                IGNORE;
  167. <Control>[a-zA-Z@0-9]*[-'=`][^ \t\n{]*          IGNORE;
  168. <Control>"\n"                                   {BEGIN Normal; NEWLINE;}
  169. <Control>[ \t]*[{]*                {BEGIN Normal; IGNORE;}
  170. <Control>.                    {yyless(0);BEGIN Normal;}
  171. <Normal>[{}\\|] /* special characters */    IGNORE;
  172. <Normal>[!?]"`"                                 IGNORE;
  173. <Normal>~                    SPACE;
  174. <Normal>{W}[']*{W}                              {   if (fWord)
  175.                             printf("%s\n", yytext);
  176.                             else
  177.                             ECHO;
  178.                         }
  179. <Normal>[0-9]+                    if (!fWord) ECHO;
  180. <Normal>(.|\n)                                  if (!fWord) ECHO;
  181. /******
  182. ** main --
  183. **    Set sbProgName to the base of arg 0.
  184. **    Set the input paths.
  185. **    Check for options
  186. **        -c        echo LaTeX \cite, \ref, and \pageref values
  187. **        -e <env-list>    list of LaTeX environments to ignore
  188. **        -l        force latex mode
  189. **        -n        do not follow \input and \include
  190. **        -s        replace control sequences with space
  191. **        -t        force tex mode
  192. **        -w        word only output
  193. **    Set the list of LaTeX environments to ignore.
  194. **    Process each input file.
  195. **    If no input files are specified on the command line, process stdin.
  196. ******/
  197. main(cArgs,rgsbArgs)
  198. int    cArgs;
  199. char    *rgsbArgs[];
  200.     char    *pch, *sbEnvList = DEFAULTENV, sbBadOpt[2];
  201.     FILE    *TexOpen();
  202.     int    fSawFile = 0, iArgs = 1;
  203.     /* get base name and decide what we are doing, detex or delatex */
  204.     if ((sbProgName = rindex(rgsbArgs[0], '/')) != NULL)
  205.         sbProgName++;
  206.     else
  207.         sbProgName = rgsbArgs[0];
  208.     if (strcmp("delatex",sbProgName) == 0)
  209.         fLatex = 1;
  210.     /* set rgsbInputPaths for use with TexOpen() */
  211.     SetInputPaths();
  212.     /* process command line options */
  213.     while (iArgs < cArgs && *(pch = rgsbArgs[iArgs]) == CHOPT) {
  214.         while (*++pch)
  215.             switch (*pch) {
  216.             case CHCITEOPT:
  217.             fCite = 1;
  218.             break;
  219.             case CHENVOPT:
  220.             sbEnvList = rgsbArgs[++iArgs];
  221.             break;
  222.             case CHLATEXOPT:
  223.             fLatex = 1;
  224.             break;
  225.             case CHNOFOLLOWOPT:
  226.             fFollow = 0;
  227.             break;
  228.             case CHSPACEOPT:
  229.             fSpace = 1;
  230.             break;
  231.             case CHTEXOPT:
  232.             fForcetex = 1;
  233.             break;
  234.             case CHWORDOPT:
  235.             fWord = 1;
  236.             break;
  237.             default:
  238.             sbBadOpt[0] = *pch;
  239.             sbBadOpt[1] = '\0';
  240.             Warning("unknown option ignored -", sbBadOpt);
  241.             }
  242.         iArgs++;
  243.     SetEnvIgnore(sbEnvList);
  244.     /* process input files */
  245.     for (; iArgs < cArgs; iArgs++) {
  246.         fSawFile++;
  247.         if ((yyin = TexOpen(rgsbArgs[iArgs])) == NULL) {
  248.         Warning("can't open file", rgsbArgs[iArgs]);
  249.         continue;;
  250.         }
  251.         BEGIN Normal;
  252.         (void)yylex();
  253.     /* if there were no input files, assume stdin */
  254.     if (!fSawFile) {
  255.         yyin = stdin;
  256.         BEGIN Normal;
  257.         (void)yylex();
  258. #ifndef FLEX_SCANNER
  259.     if (YYSTATE != Normal)
  260.         ErrorExit("input contains an unterminated mode or environment");
  261. #endif
  262.     exit(0);
  263. #ifdef FLEX_SCANNER
  264. #undef yywrap
  265. #endif
  266. /******
  267. ** yywrap -- handles EOF for lex.  Check to see if the stack of open files
  268. **    has anything on it.  If it does, set yyin to the to value.  If not
  269. **    return the termination signal for lex.
  270. ******/
  271. yywrap()
  272.     (void)fclose(yyin);
  273.     if (cfp > 0) {
  274.         yyin = rgfp[--cfp];
  275.         return(0);
  276.     return(1);
  277. /******
  278. ** SetEnvIgnore -- sets rgsbEnvIgnore to the values indicated by the
  279. **    sbEnvList.
  280. ******/
  281. SetEnvIgnore(sbEnvList)
  282. char    *sbEnvList;
  283.     csbEnvIgnore = SeparateList(sbEnvList, rgsbEnvIgnore, CHENVSEP, MAXENVS);
  284.     if (csbEnvIgnore == ERROR)
  285.         ErrorExit("The environtment list contains too many environments");
  286. /******
  287. ** BeginEnv -- checks to see if sbEnv is in the list rgsbEnvIgnore.  If it
  288. **    is, sbCurrentEnv is set to sbEnv.
  289. ******/
  290. BeginEnv(sbEnv)
  291. char    *sbEnv;
  292.     int    i;
  293.     if (!fLatex) return(0);
  294.     for (i = 0; i < csbEnvIgnore; i++)
  295.         if (strcmp(sbEnv, rgsbEnvIgnore[i]) == 0) {
  296.         (void)strcpy(sbCurrentEnv, sbEnv);
  297.         return(1);
  298.         }
  299.     return(0);
  300. /******
  301. ** EndEnv -- checks to see if sbEnv is the current environment being ignored.
  302. ******/
  303. EndEnv(sbEnv)
  304. char    *sbEnv;
  305.     if (!fLatex) return(0);
  306.     if (strcmp(sbEnv, sbCurrentEnv) == 0)
  307.         return(1);
  308.     return(0);
  309. /******
  310. ** InputFile -- push the current yyin and open sbFile.    If the open fails,
  311. **    the sbFile is ignored.
  312. ******/
  313. InputFile(sbFile)
  314. char    *sbFile;
  315.     FILE    *TexOpen();
  316.     if (!fFollow)
  317.         return;
  318.     rgfp[cfp++] = yyin;
  319.     if ((yyin = TexOpen(sbFile)) == NULL) {
  320.         Warning("can't open \\input file", sbFile);
  321.         yyin = rgfp[--cfp];
  322. /******
  323. ** IncludeFile -- if sbFile is not in the rgsbIncList, push current yyin
  324. **    and open sbFile.  If the open fails, the sbFile is ignored.
  325. ******/
  326. IncludeFile(sbFile)
  327. char    *sbFile;
  328.     FILE    *TexOpen();
  329.     if (!fFollow)
  330.         return;
  331.     if (!InList(sbFile))
  332.         return;
  333.     rgfp[cfp++] = yyin;
  334.     if ((yyin = TexOpen(sbFile)) == NULL) {
  335.         Warning("can't open \\include file", sbFile);
  336.         yyin = rgfp[--cfp];
  337. /******
  338. ** AddInclude -- adds sbFile to the rgsbIncList and increments csbIncList.
  339. **    If the include list is too long, sbFile is ignored.
  340. ******/
  341. AddInclude(sbFile)
  342. char    *sbFile;
  343.     if (!fFollow)
  344.         return;
  345.     if (csbIncList >= MAXINCLIST)
  346.         Warning("\\includeonly list is too long, ignoring", sbFile);
  347.     rgsbIncList[csbIncList] = malloc((unsigned)(strlen(sbFile) + 1));
  348.     (void)strcpy(rgsbIncList[csbIncList++], sbFile);
  349. /******
  350. ** InList -- checks to see if sbFile is in the rgsbIncList.  If there is
  351. **    no list, all files are assumed to be "in the list".
  352. ******/
  353. InList(sbFile)
  354. char    *sbFile;
  355.     char    *pch, sbBase[MAXPATHLEN];
  356.     int    i;
  357.     if (csbIncList == 0)    /* no list */
  358.         return(1);
  359.     (void)strcpy(sbBase, sbFile);
  360.     if ((pch = rindex(sbBase, '.')) != NULL)
  361.         *pch = '\0';
  362.     i = 0;
  363.     while ((i < csbIncList) && rgsbIncList[i])
  364.         if (strcmp(rgsbIncList[i++], sbBase) == 0)
  365.         return(1);
  366.     return(0);
  367. /******
  368. ** SetInputPaths -- sets rgsbInputPaths to the values indicated by the
  369. **    TEXINPUTS environment variable if set or else DEFAULTINPUTS.
  370. ******/
  371. SetInputPaths()
  372. #ifdef _DCC
  373.     char *sb, *sbPaths;
  374. #else
  375.     char *sb, *sbPaths, *getenv();
  376. #endif
  377.     if ((sb = getenv("TEXINPUTS")) == NULL)
  378.     sbPaths = DEFAULTINPUTS;
  379.     else {
  380.     sbPaths = malloc((unsigned)(strlen(sb) + 1));
  381.     (void)strcpy(sbPaths, sb);
  382.     }
  383.     csbInputPaths = SeparateList(sbPaths, rgsbInputPaths, CHPATHSEP, MAXINPUTPATHS);
  384.     if (csbInputPaths == ERROR)
  385.     ErrorExit("TEXINPUTS environment variable has too many paths");
  386. /******
  387. ** SeparateList -- takes a chSep separated list sbList, replaces the
  388. **    chSep's with NULLs and sets rgsbList[i] to the beginning of
  389. **    the ith word in sbList.  The number of words is returned.  A
  390. **    ERROR is returned if there are more than csbMax words.
  391. ******/
  392. SeparateList(sbList, rgsbList, chSep, csbMax)
  393. char    *sbList, *rgsbList[], chSep;
  394. int    csbMax;
  395.     int    csbList = 0;
  396.     while (sbList && *sbList && csbList < csbMax) {
  397.         rgsbList[csbList++] = sbList;
  398.         if (sbList = index(sbList, chSep))
  399.         *sbList++ = '\0';
  400.     return(sbList && *sbList ? ERROR : csbList);
  401. /******
  402. ** TexOpen -- tries to open sbFile in each of the rgsbInputPaths in turn.
  403. **    For each input path the following order is used:
  404. **        file.tex - must be as named, if not there go to the next path
  405. **        file.ext - random extension, try it
  406. **        file     - base name, add .tex and try it
  407. **        file     - try it as is
  408. **    Notice that if file exists in the first path and file.tex exists in
  409. **    one of the other paths, file in the first path is what is opened.
  410. **    If the sbFile begins with a '/', no paths are searched.
  411. ******/
  412. FILE *
  413. TexOpen(sbFile)
  414. char    *sbFile;
  415.     char    *pch, *sbNew;
  416.     FILE    *fp;
  417.     int    iPath;
  418.     static char    sbFullPath[MAXPATHLEN];
  419.     for (iPath = 0; iPath < csbInputPaths; iPath++) {
  420. #ifdef _DCC
  421.         if (*sbFile == ':') {       /* absolute path */
  422. #else
  423.         if (*sbFile == ':') {       /* absolute path */
  424. #endif
  425.         (void)sprintf(sbFullPath, "%s", sbFile);
  426.         iPath = csbInputPaths;    /* only check once */
  427.         } else
  428. #ifdef _DCC
  429.           if(0 == strcmp(rgsbInputPaths[iPath],".")) {
  430.         (void) sprintf(sbFullPath, "%s", sbFile);
  431.           } else {
  432.         char *tmp = rgsbInputPaths[iPath];
  433.         if(tmp[strlen(tmp)-1] == ':' || tmp[strlen(tmp)-1] == '/') {
  434.           (void)sprintf(sbFullPath, "%s%s", rgsbInputPaths[iPath], sbFile);
  435.         } else {
  436.           (void)sprintf(sbFullPath, "%s/%s", rgsbInputPaths[iPath], sbFile);
  437.           }
  438. #else
  439.         (void)sprintf(sbFullPath, "%s/%s", rgsbInputPaths[iPath], sbFile);
  440. #endif
  441.         /* If sbFile ends in .tex then it must be there */
  442.         if ((pch = rindex(sbFullPath, '@')) != NULL
  443.             && (strcmp(pch, ".tex") == 0))
  444.         if ((fp = fopen(sbFullPath, "r")) != NULL)
  445.             return(fp);
  446.         else
  447.             continue;
  448.         /* if .<ext> then try to open it.  the '.' represents   */
  449.         /* the beginning of an extension if it is not the first */
  450.         /* character and it does not follow a '.' or a '/'      */
  451.         if (pch != NULL && pch > &(sbFullPath[0])
  452.             && *(pch - 1) != '.' && *(pch - 1) != '/'
  453.             && (fp = fopen(sbFullPath, "r")) != NULL)
  454.         return(fp);
  455.         /* just base name, add .tex to the name */
  456.         sbNew = malloc((unsigned)(strlen(sbFullPath) + 5));
  457.         (void)strcpy(sbNew, sbFullPath);
  458.         (void)strcat(sbNew, ".tex");
  459.         if ((fp = fopen(sbNew, "r")) != NULL)
  460.         return(fp);
  461.         /* try sbFile regardless */
  462.         if ((fp = fopen(sbFullPath, "r")) != NULL)
  463.         return(fp);
  464.     return((FILE *)NULL);
  465. /******
  466. ** Warning -- print a warning message preceded by the program name.
  467. ******/
  468. Warning(sb1, sb2)
  469. char    *sb1, *sb2;
  470.     fprintf(stderr, "%s: warning: %s %s\n", sbProgName, sb1, sb2);
  471. /******
  472. ** ErrorExit -- print an error message preceded by the program name.
  473. **    Stdout is flushed and detex exits.
  474. ******/
  475. ErrorExit(sb1)
  476. char    *sb1;
  477.     (void)fflush(stdout);
  478.     fprintf(stderr, "%s: error: %s\n", sbProgName, sb1);
  479.     exit(1);
  480.