home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / detex24.lha / detex.l (.txt) < prev    next >
LaTeX Document  |  1993-01-02  |  15KB  |  464 lines

  1. #ifndef lint
  2. static char    rcsid[] = "$Header: /usr/src/local/bin/detex/RCS/detex.l,v 2.14 1992/09/02 15:35:44 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. #include "detex.h"
  12. #ifdef USG
  13. #include <string.h>
  14. #define    index    strchr
  15. #define    rindex    strrchr
  16. #else
  17. #include <strings.h>
  18. #endif
  19. #ifndef MAXPATHLEN
  20. #include <sys/param.h>
  21. #endif
  22. #define    LaBEGIN        if (fLatex) BEGIN
  23. #define    CITEBEGIN    if (fLatex && !fCite) BEGIN
  24. #define    IGNORE        if (fSpace && !fWord) putchar(' ')
  25. #define    SPACE        if (!fWord) putchar(' ')
  26. #define    NEWLINE        if (!fWord) putchar('\n')
  27. #ifdef FLEX_SCANNER
  28. #undef yywrap
  29. #endif
  30. #ifndef __STDC__
  31. char    *malloc();
  32. #else
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <fcntl.h>
  36. #include "detex_protos.h"
  37. #endif
  38. char    *rgsbEnvIgnore[MAXENVS];    /* list of environments ignored */
  39. char    *rgsbIncList[MAXINCLIST];    /* list of includeonly files */
  40. char    *rgsbInputPaths[MAXINPUTPATHS];    /* list of input paths in order */
  41. char    sbCurrentEnv[CCHMAXENV];    /* current environment being ignored */
  42. char    *sbProgName;            /* name we were invoked with */
  43. FILE    *rgfp[NOFILE+1];        /* stack of input/include files */
  44. int    cfp = 0;            /* count of files in stack */
  45. int    cOpenBrace = 0;            /* count of `{' in <LaMacro2> */
  46. int    csbEnvIgnore;            /* count of environments ignored */
  47. int    csbIncList = 0;            /* count of includeonly files */
  48. int    csbInputPaths;            /* count of input paths */
  49. int    fLatex = 0;            /* flag to indicated delatex */
  50. int    fWord = 0;            /* flag for -w option */
  51. int    fFollow = 1;            /* flag to follow input/include */
  52. int    fCite = 0;            /* flag to echo \cite and \ref args */
  53. int    fSpace = 0;            /* flag to replace \cs with space */
  54. int    fForcetex = 0;            /* flag to inhibit latex mode */
  55. S    [ \t\n]*
  56. W    [a-zA-Z]+
  57. %Start Define Display IncludeOnly Input Math Normal Control
  58. %Start LaBegin LaDisplay LaEnd LaEnv LaFormula LaInclude
  59. %Start LaMacro LaMacro2 LaVerbatim
  60. <Normal>"%".*        /* ignore comments */    ;
  61. <Normal>"\\begin"{S}"{"{S}"document"{S}"}"    {fLatex = !fForcetex; IGNORE;}
  62. <Normal>"\\begin"     /* environment start */    {LaBEGIN LaBegin; IGNORE;}
  63. <LaBegin>{S}"{"{S}"verbatim"{S}"}"        {   if (BeginEnv("verbatim"))
  64.                             BEGIN LaEnv;
  65.                             else
  66.                             BEGIN LaVerbatim;
  67.                             IGNORE;
  68.                         }
  69. <LaVerbatim>"\\end"{S}"{"{S}"verbatim"{S}"}" /* verbatim mode */    {BEGIN Normal; IGNORE;}
  70. <LaVerbatim>.                    ECHO;
  71. <LaBegin>{W}                    {   if (BeginEnv(yytext))
  72.                             BEGIN LaEnv;
  73.                             else
  74.                             BEGIN LaMacro;
  75.                             IGNORE;
  76.                         }
  77. <LaBegin>"\n"                    NEWLINE;
  78. <LaBegin>.                    ;
  79. <LaEnv>"\\end"  /* absorb some environments */    {LaBEGIN LaEnd; IGNORE;}
  80. <LaEnv>"\n"                    NEWLINE;
  81. <LaEnv>.                    ;
  82. <LaEnd>{W}         /* end environment */    {   if (EndEnv(yytext))
  83.                             BEGIN Normal;
  84.                             IGNORE;
  85.                         }
  86. <LaEnd>"}"                    {BEGIN LaEnv; IGNORE;}
  87. <LaEnd>"\n"                    NEWLINE;
  88. <LaEnd>.                    ;
  89. <Normal>"\\bibitem"        /* ignore args  */    {LaBEGIN LaMacro2; IGNORE;}
  90. <Normal>"\\bibliography"    /* of these \cs */    {LaBEGIN LaMacro; IGNORE;}
  91. <Normal>"\\bibstyle"                {LaBEGIN LaMacro; IGNORE;}
  92. <Normal>"\\cite"                {CITEBEGIN LaMacro2; IGNORE;}
  93. <Normal>"\\documentstyle"            {LaBEGIN LaMacro; IGNORE;}
  94. <Normal>"\\end"                    {LaBEGIN LaMacro; IGNORE;}
  95. <Normal>"\\index"                {LaBEGIN LaMacro2; SPACE;}
  96. <Normal>"\\label"                {LaBEGIN LaMacro; IGNORE;}
  97. <Normal>"\\pageref"                {CITEBEGIN LaMacro; IGNORE;}
  98. <Normal>"\\pagestyle"                {LaBEGIN LaMacro; IGNORE;}
  99. <Normal>"\\ref"                    {CITEBEGIN LaMacro; IGNORE;}
  100. <Normal>"\\setcounter"                {LaBEGIN LaMacro; IGNORE;}
  101. <Normal>"\\verb" /* ignore \verb<char>...<char> */ {   if (fLatex) {
  102.                              char verbchar, c;
  103.                              verbchar = input();
  104.                              while ((c = input()) != verbchar)
  105.                                 if (c == '\n')
  106.                                 NEWLINE;
  107.                             }
  108.                             IGNORE;
  109.                         }
  110. <LaMacro>"}"                    BEGIN Normal;
  111. <LaMacro>"\n"                    NEWLINE;
  112. <LaMacro>.                    ;
  113. <LaMacro2>"{"                    {   cOpenBrace++; }
  114. <LaMacro2>"}"                    {   cOpenBrace--;
  115.                             if (cOpenBrace == 0)
  116.                             BEGIN Normal;
  117.                         }
  118. <LaMacro2>"\n"                    NEWLINE;
  119. <LaMacro2>.                    ;
  120. <Normal>"\\def"        /* ignore def begin */    {BEGIN Define; IGNORE;}
  121. <Define>"{"                    BEGIN Normal;
  122. <Define>"\n"                    NEWLINE;
  123. <Define>.                    ;
  124. <Normal>"\\("        /* formula mode */    {LaBEGIN LaFormula; IGNORE;}
  125. <LaFormula>"\\)"                BEGIN Normal;
  126. <LaFormula>"\n"                    NEWLINE;
  127. <LaFormula>.                    ;
  128. <Normal>"\\["        /* display mode */    {LaBEGIN LaDisplay; IGNORE;}
  129. <LaDisplay>"\\]"                BEGIN Normal;
  130. <LaDisplay>"\n"                    NEWLINE;
  131. <LaDisplay>.                    ;
  132. <Normal>"$$"        /* display mode */    {BEGIN Display; IGNORE;}
  133. <Display>"$$"                    BEGIN Normal;
  134. <Display>"\n"                    NEWLINE;
  135. <Display>.                    ;
  136. <Normal>"$"        /* math mode */        {BEGIN Math; IGNORE;}
  137. <Math>"$"                    BEGIN Normal;
  138. <Math>"\n"                    NEWLINE;
  139. <Math>"\\$"                    ;
  140. <Math>.                        ;
  141. <Normal>"\\include"    /* process files */    {LaBEGIN LaInclude; IGNORE;}
  142. <LaInclude>[^{ \t\n}]+                {   IncludeFile(yytext);
  143.                             BEGIN Normal;
  144.                         }
  145. <LaInclude>"\n"                    NEWLINE;
  146. <LaInclude>.                    ;
  147. <Normal>"\\includeonly"                {BEGIN IncludeOnly; IGNORE;}
  148. <IncludeOnly>[^{ \t,\n}]+            AddInclude(yytext);
  149. <IncludeOnly>"}"                {   if (csbIncList == 0)
  150.                             rgsbIncList[csbIncList++] = '\0';
  151.                             BEGIN Normal;
  152.                         }
  153. <IncludeOnly>"\n"                NEWLINE;
  154. <IncludeOnly>.                    ;
  155. <Normal>"\\input"                {BEGIN Input; IGNORE;}
  156. <Input>[^{ \t\n}]+                {   InputFile(yytext);
  157.                             BEGIN Normal;
  158.                         }
  159. <Input>"\n"                    NEWLINE;
  160. <Input>.                    ;
  161. <Normal>\\(aa|AA|ae|AE|oe|OE|ss)" " /* handle ligatures */ {printf("%.2s", yytext+1);}
  162. <Normal>\\[OoijLl]" "                {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(int cArgs, char *rgsbArgs[])
  198.     char    *pch, *sbEnvList = DEFAULTENV, sbBadOpt[2];
  199. #ifndef __STDC__
  200.     FILE    *TexOpen();
  201. #endif
  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. /******
  264. ** yywrap -- handles EOF for lex.  Check to see if the stack of open files
  265. **    has anything on it.  If it does, set yyin to the to value.  If not
  266. **    return the termination signal for lex.
  267. ******/
  268. int yywrap(void)
  269.     (void)fclose(yyin);
  270.     if (cfp > 0) {
  271.         yyin = rgfp[--cfp];
  272.         return(0);
  273.     return(1);
  274. /******
  275. ** SetEnvIgnore -- sets rgsbEnvIgnore to the values indicated by the
  276. **    sbEnvList.
  277. ******/
  278. void SetEnvIgnore(char *sbEnvList)
  279.     csbEnvIgnore = SeparateList(sbEnvList, rgsbEnvIgnore, CHENVSEP, MAXENVS);
  280.     if (csbEnvIgnore == ERROR)
  281.         ErrorExit("The environtment list contains too many environments");
  282. /******
  283. ** BeginEnv -- checks to see if sbEnv is in the list rgsbEnvIgnore.  If it
  284. **    is, sbCurrentEnv is set to sbEnv.
  285. ******/
  286. int BeginEnv(char *sbEnv)
  287.     int    i;
  288.     if (!fLatex) return(0);
  289.     for (i = 0; i < csbEnvIgnore; i++)
  290.         if (strcmp(sbEnv, rgsbEnvIgnore[i]) == 0) {
  291.         (void)strcpy(sbCurrentEnv, sbEnv);
  292.         return(1);
  293.         }
  294.     return(0);
  295. /******
  296. ** EndEnv -- checks to see if sbEnv is the current environment being ignored.
  297. ******/
  298. int EndEnv(char *sbEnv)
  299.     if (!fLatex) return(0);
  300.     if (strcmp(sbEnv, sbCurrentEnv) == 0)
  301.         return(1);
  302.     return(0);
  303. /******
  304. ** InputFile -- push the current yyin and open sbFile.  If the open fails,
  305. **    the sbFile is ignored.
  306. ******/
  307. void InputFile(char *sbFile)
  308. #ifndef __STDC__
  309.     FILE    *TexOpen();
  310. #endif
  311.     if (!fFollow)
  312.         return;
  313.     rgfp[cfp++] = yyin;
  314.     if ((yyin = TexOpen(sbFile)) == NULL) {
  315.         Warning("can't open \\input file", sbFile);
  316.         yyin = rgfp[--cfp];
  317. /******
  318. ** IncludeFile -- if sbFile is not in the rgsbIncList, push current yyin
  319. **    and open sbFile.  If the open fails, the sbFile is ignored.
  320. ******/
  321. void IncludeFile(char *sbFile)
  322. #ifndef __STDC__
  323.     FILE    *TexOpen();
  324. #endif
  325.     if (!fFollow)
  326.         return;
  327.     if (!InList(sbFile))
  328.         return;
  329.     rgfp[cfp++] = yyin;
  330.     if ((yyin = TexOpen(sbFile)) == NULL) {
  331.         Warning("can't open \\include file", sbFile);
  332.         yyin = rgfp[--cfp];
  333. /******
  334. ** AddInclude -- adds sbFile to the rgsbIncList and increments csbIncList.
  335. **    If the include list is too long, sbFile is ignored.
  336. ******/
  337. void AddInclude(char *sbFile)
  338.     if (!fFollow)
  339.         return;
  340.     if (csbIncList >= MAXINCLIST)
  341.         Warning("\\includeonly list is too long, ignoring", sbFile);
  342.     rgsbIncList[csbIncList] = malloc((unsigned)(strlen(sbFile) + 1));
  343.     (void)strcpy(rgsbIncList[csbIncList++], sbFile);
  344. /******
  345. ** InList -- checks to see if sbFile is in the rgsbIncList.  If there is
  346. **    no list, all files are assumed to be "in the list".
  347. ******/
  348. int InList(char *sbFile)
  349.     char    *pch, sbBase[MAXPATHLEN];
  350.     int    i;
  351.     if (csbIncList == 0)    /* no list */
  352.         return(1);
  353.     (void)strcpy(sbBase, sbFile);
  354.     if ((pch = rindex(sbBase, '.')) != NULL)
  355.         *pch = '\0';
  356.     i = 0;
  357.     while ((i < csbIncList) && rgsbIncList[i])
  358.         if (strcmp(rgsbIncList[i++], sbBase) == 0)
  359.             return(1);
  360.     return(0);
  361. /******
  362. ** SetInputPaths -- sets rgsbInputPaths to the values indicated by the
  363. **    TEXINPUTS environment variable if set or else DEFAULTINPUTS.
  364. ******/
  365. void SetInputPaths(void)
  366.     char *sb, *sbPaths, *getenv();
  367.     if ((sb = getenv("TEXINPUTS")) == NULL)
  368.     sbPaths = DEFAULTINPUTS;
  369.     else {
  370.     sbPaths = malloc((unsigned)(strlen(sb) + 1));
  371.     (void)strcpy(sbPaths, sb);
  372.     }
  373.     csbInputPaths = SeparateList(sbPaths, rgsbInputPaths, CHPATHSEP, MAXINPUTPATHS);
  374.     if (csbInputPaths == ERROR)
  375.     ErrorExit("TEXINPUTS environment variable has too many paths");
  376. /******
  377. ** SeparateList -- takes a chSep separated list sbList, replaces the
  378. **    chSep's with NULLs and sets rgsbList[i] to the beginning of
  379. **    the ith word in sbList.  The number of words is returned.  A
  380. **    ERROR is returned if there are more than csbMax words.
  381. ******/
  382. int SeparateList(char *sbList, char *rgsbList[], char chSep, int csbMax)
  383.     int    csbList = 0;
  384.     while (sbList && *sbList && csbList < csbMax) {
  385.         rgsbList[csbList++] = sbList;
  386.         if (sbList = index(sbList, chSep))
  387.         *sbList++ = '\0';
  388.     return(sbList && *sbList ? ERROR : csbList);
  389. /******
  390. ** TexOpen -- tries to open sbFile in each of the rgsbInputPaths in turn.
  391. **    For each input path the following order is used:
  392. **        file.tex - must be as named, if not there go to the next path
  393. **        file.ext - random extension, try it
  394. **        file     - base name, add .tex and try it
  395. **        file     - try it as is
  396. **    Notice that if file exists in the first path and file.tex exists in
  397. **    one of the other paths, file in the first path is what is opened.
  398. **    If the sbFile begins with a '/', no paths are searched.
  399. ******/
  400. FILE *TexOpen(char *sbFile)
  401.     char    *pch, *sbNew;
  402.     FILE    *fp;
  403.     int    iPath;
  404.     static char    sbFullPath[MAXPATHLEN];
  405.     for (iPath = 0; iPath < csbInputPaths; iPath++) {
  406. #ifdef _AMIGA
  407.         if(strchr(sbFile,':')) {
  408. #else
  409.         if (*sbFile == '/') {    /* absolute path */
  410. #endif
  411.             (void)sprintf(sbFullPath, "%s", sbFile);
  412.             iPath = csbInputPaths;    /* only check once */
  413.         } else {
  414. #ifdef _AMIGA
  415.             if(0 == strcmp(rgsbInputPaths[iPath],".")) {
  416.                 (void) sprintf(sbFullPath, "%s", sbFile);
  417.             } else {
  418.                 char *tmp = rgsbInputPaths[iPath];
  419.                 if(tmp[strlen(tmp)-1] == ':' || tmp[strlen(tmp)-1] == '/') {
  420.                     (void)sprintf(sbFullPath, "%s%s", rgsbInputPaths[iPath], sbFile);
  421.                 } else {
  422.                     (void)sprintf(sbFullPath, "%s/%s", rgsbInputPaths[iPath], sbFile);
  423.                 }
  424. #else
  425.             (void)sprintf(sbFullPath, "%s/%s", rgsbInputPaths[iPath], sbFile);
  426. #endif
  427.         /* If sbFile ends in .tex then it must be there */
  428.         if ((pch = rindex(sbFullPath, '.')) != NULL
  429.             && (strcmp(pch, ".tex") == 0))
  430.         if ((fp = fopen(sbFullPath, "r")) != NULL)
  431.             return(fp);
  432.         else
  433.             continue;
  434.         /* if .<ext> then try to open it.  the '.' represents   */
  435.         /* the beginning of an extension if it is not the first */
  436.         /* character and it does not follow a '.' or a '/'      */
  437.         if (pch != NULL && pch > &(sbFullPath[0])
  438.                     && *(pch - 1) != '.' && *(pch - 1) != '/'
  439.             && (fp = fopen(sbFullPath, "r")) != NULL)
  440.         return(fp);
  441.         /* just base name, add .tex to the name */
  442.         sbNew = malloc((unsigned)(strlen(sbFullPath) + 5));
  443.         (void)strcpy(sbNew, sbFullPath);
  444.         (void)strcat(sbNew, ".tex");
  445.         if ((fp = fopen(sbNew, "r")) != NULL)
  446.         return(fp);
  447.         /* try sbFile regardless */
  448.         if ((fp = fopen(sbFullPath, "r")) != NULL)
  449.         return(fp);
  450.     return((FILE *)NULL);
  451. /******
  452. ** Warning -- print a warning message preceded by the program name.
  453. ******/
  454. void Warning(char *sb1, char *sb2)
  455.     fprintf(stderr, "%s: warning: %s %s\n", sbProgName, sb1, sb2);
  456. /******
  457. ** ErrorExit -- print an error message preceded by the program name.
  458. **    Stdout is flushed and detex exits.
  459. ******/
  460. void ErrorExit(char *sb1)
  461.     (void)fflush(stdout);
  462.     fprintf(stderr, "%s: error: %s\n", sbProgName, sb1);
  463.     exit(1);
  464.