home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / explode / explode.c < prev    next >
C/C++ Source or Header  |  1989-09-23  |  7KB  |  332 lines

  1. /*
  2.  * explode -- an extact function for a latex-flavored tangle.
  3.  */
  4. #include <stdio.h>
  5. #include <strings.h>
  6.  
  7. #define MAXLINE    256
  8. #define OK    0
  9. char    *ProgName = NULL;
  10. typedef enum {NO=0,FILENAME,BEGIN_VERBATIM,END_VERBATIM} KEY;
  11.  
  12.  void
  13. main(argc,argv) int argc; char *argv[]; {
  14.     int    rc = 0, /* Return code from explode. */
  15.             i;
  16.     FILE    *fp, *lopen();
  17.  
  18.     ProgName = argv[0];
  19.     if (argc < 2 && isatty(0)) {
  20.         (void) fprintf(stderr,"Usage: %s file[.tex]\n",
  21.                ProgName);
  22.         exit(1);
  23.     }
  24.     if (!isatty(0)) {
  25.         rc = explode(stdin);
  26.     }
  27.     else {
  28.         for (i=1; i < argc; i++) {
  29.                 /* printf("argv[%d] = '%s'\n",i,argv[i]); */
  30.             if ((fp= lopen(argv[i],"r",".tex")) == NULL) {
  31.                 (void) fprintf(stderr,
  32.                     "%s: %s \"%s\", ignored.\n",
  33.                     ProgName, "can't open input file",
  34.                     argv[i]);
  35.                 continue;
  36.             }
  37.             else {
  38.                 rc = explode(fp);
  39.                 (void) fclose(fp);
  40.             }
  41.         }
  42.     }
  43.     exit(rc);
  44. }
  45.  
  46. /*
  47.  * explode -- the main function, which supervises parsing
  48.  *      and output-file bookkeeping.
  49.  */
  50.  int
  51. explode(fp) FILE *fp; {
  52.     char    line[MAXLINE],      /* A place to put the line. */
  53.             operand[MAXLINE];   /* The keyword's parameter. */
  54.     FILE    *outFp,             /* Current output file. */
  55.             *tFp,               /* Temporary fp. */
  56.              *initialFile(),     /* Initial output file (/dev/null) */
  57.             *beginFile(),       /* Start writing to taht file. */
  58.             *endFile();         /* Stop writing to it. */
  59.     int    initiateFile();     /* Associate a name with an fp. */
  60.  
  61.     KEY    hasKeyWord();
  62.  
  63.     if ((outFp= initialFile()) == NULL) {
  64.               /* Assumed infallible. */
  65.               (void) fprintf(stderr,"%s: unable to open \"%s\", %s.\n",
  66.             ProgName,"/dev/null","aborting");
  67.           exit(3);
  68.     }
  69.     while (fgets(line,sizeof(line),fp) != NULL) {
  70.         switch (hasKeyWord(line,operand)) {
  71.         case NO: /* Just write the line. */
  72.                /* printf("body line: %s",line); */
  73.                (void) fputs(line,outFp);
  74.                break;
  75.         case FILENAME: /* Collect a new filename to use. */
  76.                /* printf("file line: %s, %s",operand,line); */
  77.                if ( !initiateFile(operand)) {
  78.                        (void) fprintf(stderr, 
  79.                            "%s: can't open output file \"%s\", %s.\n",
  80.                        ProgName, operand, "aborting");
  81.                    exit(3);
  82.                }
  83.                break;
  84.         case BEGIN_VERBATIM: /* Start writing to named file. */
  85.                /* printf("begin line: %s, %s",operand,line); */
  86.                if ((tFp= beginFile()) != NULL) {
  87.                    outFp = tFp;
  88.                }
  89.                else {
  90.                    /* It's "\begin{verbatim}" with no current file. */
  91.                    (void) fputs(line,outFp);
  92.                } 
  93.                break;
  94.         case END_VERBATIM: /* Stop writing to that file. */
  95.                /* printf("end line %s, %s",operand,line); */
  96.                if ((tFp= endFile()) != NULL) {
  97.                    outFp = tFp;
  98.                }
  99.                else {
  100.                    /* It's "\end{verbatim} with no current file". */
  101.                    (void) fputs(line,outFp);
  102.                } 
  103.                break;
  104.         }
  105.      }
  106.     return OK;
  107. }
  108.  
  109. /*
  110.  * lopen -- local open, sees if there's a file with an optional suffix.
  111.  */
  112.  FILE *
  113. lopen(name,mode,ext) char *name, *mode, *ext; {
  114.     FILE    *fp, *fopen();
  115.     char    buffer[MAXLINE],
  116.             *strcat(), *strcpy();
  117.  
  118.     if ((fp= fopen(name,mode)) != NULL) {
  119.         return fp;
  120.     }
  121.     (void) strcat(strcpy(buffer,name),ext);
  122.     fp = fopen(buffer,mode);
  123.     return fp;
  124. }
  125.  
  126. /*
  127.  * hasKeyWord -- see if the keyword appears in the line,
  128.  *      return either NO, FILENAME, BEGIN_VERBATIM or END_VERBATIM and
  129.  *      a pointer to a null-terminated string containing
  130.  *      the parameter.  Also produces error messages if
  131.  *      the keyword-phrase is misparsed.
  132.  */
  133. #define strchr(s,c) index(s,c)
  134. #define streq(s1,s2) (strncmp(s1,s2,strlen(s2))==0)
  135.  KEY
  136. hasKeyWord(line,operand) char *line; char *operand; {
  137.         register char *p; /* Pointer to current position in string. */
  138.         KEY      rc;      /* Result. */
  139.     char     *skipTo();
  140.     void     terminate(), unTerminate();
  141.  
  142.         if ((p= strchr(line,'\\')) == NULL) {
  143.             return NO;
  144.     }
  145.     else if (streq(p,"\\file{")) {
  146.            rc = FILENAME;
  147.     }
  148.     else if (streq(line,"\\begin{verbatim}")) {
  149.             rc = BEGIN_VERBATIM;
  150.     }
  151.     else if (streq(line,"\\end{verbatim}")) {
  152.             rc = END_VERBATIM;
  153.     }
  154.     else {
  155.             return NO;
  156.     }
  157.     /* It found one! Stuff "operand" with the parameter value. */
  158.         p = skipTo(p,'{') + 1;
  159.     terminate(p,'}');
  160.     (void) strcpy(operand,p);
  161.     unTerminate(p,'}');
  162.     return rc;
  163. }
  164.  
  165. /*
  166. ** string utilities 
  167. */
  168.  char *
  169. skipTo(p,c) register char *p; char c; {
  170.         while (*p && *p != c)
  171.             p++;
  172.     return p;
  173.       }
  174.  
  175.  void
  176. terminate(from,at) char *from, at; {
  177.         while (*from && *from != at)
  178.             from++;
  179.     if (!*from)
  180.             return;
  181.     *from = '\0';
  182.     return;
  183. }
  184.  
  185.  void
  186. unTerminate(from,with) char *from, with; {
  187.         while (*from)
  188.             from++;
  189.     *from = with;
  190.     return;
  191. }
  192.  
  193. /*
  194.  * strsave -- allocate enopugh space for a string & its terminating null.
  195.  */
  196.  char *
  197. strsave(s) char *s; {
  198.         char    *p, *malloc(), *strcpy();
  199.  
  200.     if ((p= malloc((unsigned)strlen(s)+1)) != NULL) {
  201.             return strcpy(p,s);
  202.     }
  203.     else {
  204.             return NULL;
  205.     }
  206. }
  207.  
  208. /*
  209. ** File -- output-file managment package.
  210. **      Depends on table package.
  211. */
  212. #define CURRENT "The current file"
  213. typedef struct {
  214.         char *name;
  215.     FILE *fp;
  216. } TABLE;
  217.  
  218.  
  219. /*
  220.  * initialFile -- create the initial output file (/dev/null).
  221.  */
  222.  FILE *
  223. initialFile() {
  224.         FILE    *fp, *fopen();
  225.     TABLE   *addToTable();
  226.  
  227.     if ((fp= fopen("/dev/null","w")) != NULL 
  228.        && addToTable("/dev/null",fp) != NULL) {
  229.             return fp;
  230.     }
  231.     else {
  232.             return (FILE *) NULL;
  233.     }
  234. }
  235.  
  236. /*
  237.  * initiateFile -- get a file pointer for the named file & save it.
  238.  */
  239.  int
  240. initiateFile(name) char *name; {
  241.     TABLE   *getFromTable(), *addToTable();
  242.     FILE    *fp, *fopen();
  243.  
  244.            if (getFromTable(name) != NULL) {
  245.             return 1;
  246.     }
  247.     else if ((fp= fopen(name,"w")) == NULL) {
  248.             return 0;
  249.     }
  250.     else {
  251.             return addToTable(name,fp)? 1: 0;
  252.     }
  253. }
  254.  
  255. /*
  256.  * beginFile --  start writing to that file.
  257.  */
  258.  FILE *
  259. beginFile() {
  260.         TABLE   *t, *getFromTable();
  261.  
  262.         if ((t= getFromTable(CURRENT)) != NULL) {
  263.             return t->fp;
  264.     }
  265.     else {
  266.             return NULL;
  267.         }
  268. }
  269.  
  270. /*
  271.  * endFile -- stop writing to it.
  272.  */
  273.  FILE *
  274. endFile() {    
  275.         TABLE   *getFromTable();
  276.  
  277.         if (getFromTable(CURRENT) != NULL) {
  278.             /* Return the replacement. */
  279.             return getFromTable("/dev/null")->fp;
  280.     }
  281.     else {
  282.             /* Otherwise don't stop using it. */
  283.             return (FILE *) NULL;
  284.     }
  285. }
  286.  
  287.  
  288. /*
  289.  * 
  290.  */
  291. #define NFILES 30
  292. TABLE   Table[NFILES];
  293. static int CurrentFile = -1;
  294.  
  295.  TABLE *
  296. addToTable(name,fp) char *name; FILE *fp; {
  297.         static int lastLookedAt = 0;
  298.     int     i;
  299.     char    *strsave();
  300.     TABLE   *t, *getFromTable();
  301.  
  302.         if ((t= getFromTable(name)) != NULL) {
  303.             return (TABLE *) t;
  304.     }
  305.     else {
  306.             for (i=lastLookedAt; i < NFILES; i++) {
  307.                 if (Table[i].name == NULL) {
  308.                     Table[i].name = strsave(name);
  309.                     Table[i].fp = fp;
  310.                 CurrentFile = i;
  311.                 return &Table[i];
  312.             }
  313.         }
  314.         return (TABLE *) NULL;
  315.     }
  316. }
  317.  
  318.  TABLE *
  319. getFromTable(name) char *name; {
  320.         int     i;
  321.  
  322.     if (streq(name,CURRENT)) {
  323.         return (CurrentFile == -1)?  (TABLE *) NULL: &Table[CurrentFile];
  324.     }
  325.         for (i=0; i < NFILES && Table[i].name != NULL; i++) {
  326.             if (streq(Table[i].name,name) != NULL) {
  327.                 return &Table[i];
  328.         }
  329.     }
  330.         return (TABLE *) NULL;
  331. }
  332.