home *** CD-ROM | disk | FTP | other *** search
- /*
- * explode -- an extact function for a latex-flavored tangle.
- */
- #include <stdio.h>
- #include <strings.h>
-
- #define MAXLINE 256
- #define OK 0
- char *ProgName = NULL;
- typedef enum {NO=0,FILENAME,BEGIN_VERBATIM,END_VERBATIM} KEY;
-
- void
- main(argc,argv) int argc; char *argv[]; {
- int rc = 0, /* Return code from explode. */
- i;
- FILE *fp, *lopen();
-
- ProgName = argv[0];
- if (argc < 2 && isatty(0)) {
- (void) fprintf(stderr,"Usage: %s file[.tex]\n",
- ProgName);
- exit(1);
- }
- if (!isatty(0)) {
- rc = explode(stdin);
- }
- else {
- for (i=1; i < argc; i++) {
- /* printf("argv[%d] = '%s'\n",i,argv[i]); */
- if ((fp= lopen(argv[i],"r",".tex")) == NULL) {
- (void) fprintf(stderr,
- "%s: %s \"%s\", ignored.\n",
- ProgName, "can't open input file",
- argv[i]);
- continue;
- }
- else {
- rc = explode(fp);
- (void) fclose(fp);
- }
- }
- }
- exit(rc);
- }
-
- /*
- * explode -- the main function, which supervises parsing
- * and output-file bookkeeping.
- */
- int
- explode(fp) FILE *fp; {
- char line[MAXLINE], /* A place to put the line. */
- operand[MAXLINE]; /* The keyword's parameter. */
- FILE *outFp, /* Current output file. */
- *tFp, /* Temporary fp. */
- *initialFile(), /* Initial output file (/dev/null) */
- *beginFile(), /* Start writing to taht file. */
- *endFile(); /* Stop writing to it. */
- int initiateFile(); /* Associate a name with an fp. */
-
- KEY hasKeyWord();
-
- if ((outFp= initialFile()) == NULL) {
- /* Assumed infallible. */
- (void) fprintf(stderr,"%s: unable to open \"%s\", %s.\n",
- ProgName,"/dev/null","aborting");
- exit(3);
- }
- while (fgets(line,sizeof(line),fp) != NULL) {
- switch (hasKeyWord(line,operand)) {
- case NO: /* Just write the line. */
- /* printf("body line: %s",line); */
- (void) fputs(line,outFp);
- break;
- case FILENAME: /* Collect a new filename to use. */
- /* printf("file line: %s, %s",operand,line); */
- if ( !initiateFile(operand)) {
- (void) fprintf(stderr,
- "%s: can't open output file \"%s\", %s.\n",
- ProgName, operand, "aborting");
- exit(3);
- }
- break;
- case BEGIN_VERBATIM: /* Start writing to named file. */
- /* printf("begin line: %s, %s",operand,line); */
- if ((tFp= beginFile()) != NULL) {
- outFp = tFp;
- }
- else {
- /* It's "\begin{verbatim}" with no current file. */
- (void) fputs(line,outFp);
- }
- break;
- case END_VERBATIM: /* Stop writing to that file. */
- /* printf("end line %s, %s",operand,line); */
- if ((tFp= endFile()) != NULL) {
- outFp = tFp;
- }
- else {
- /* It's "\end{verbatim} with no current file". */
- (void) fputs(line,outFp);
- }
- break;
- }
- }
- return OK;
- }
-
- /*
- * lopen -- local open, sees if there's a file with an optional suffix.
- */
- FILE *
- lopen(name,mode,ext) char *name, *mode, *ext; {
- FILE *fp, *fopen();
- char buffer[MAXLINE],
- *strcat(), *strcpy();
-
- if ((fp= fopen(name,mode)) != NULL) {
- return fp;
- }
- (void) strcat(strcpy(buffer,name),ext);
- fp = fopen(buffer,mode);
- return fp;
- }
-
- /*
- * hasKeyWord -- see if the keyword appears in the line,
- * return either NO, FILENAME, BEGIN_VERBATIM or END_VERBATIM and
- * a pointer to a null-terminated string containing
- * the parameter. Also produces error messages if
- * the keyword-phrase is misparsed.
- */
- #define strchr(s,c) index(s,c)
- #define streq(s1,s2) (strncmp(s1,s2,strlen(s2))==0)
- KEY
- hasKeyWord(line,operand) char *line; char *operand; {
- register char *p; /* Pointer to current position in string. */
- KEY rc; /* Result. */
- char *skipTo();
- void terminate(), unTerminate();
-
- if ((p= strchr(line,'\\')) == NULL) {
- return NO;
- }
- else if (streq(p,"\\file{")) {
- rc = FILENAME;
- }
- else if (streq(line,"\\begin{verbatim}")) {
- rc = BEGIN_VERBATIM;
- }
- else if (streq(line,"\\end{verbatim}")) {
- rc = END_VERBATIM;
- }
- else {
- return NO;
- }
- /* It found one! Stuff "operand" with the parameter value. */
- p = skipTo(p,'{') + 1;
- terminate(p,'}');
- (void) strcpy(operand,p);
- unTerminate(p,'}');
- return rc;
- }
-
- /*
- ** string utilities
- */
- char *
- skipTo(p,c) register char *p; char c; {
- while (*p && *p != c)
- p++;
- return p;
- }
-
- void
- terminate(from,at) char *from, at; {
- while (*from && *from != at)
- from++;
- if (!*from)
- return;
- *from = '\0';
- return;
- }
-
- void
- unTerminate(from,with) char *from, with; {
- while (*from)
- from++;
- *from = with;
- return;
- }
-
- /*
- * strsave -- allocate enopugh space for a string & its terminating null.
- */
- char *
- strsave(s) char *s; {
- char *p, *malloc(), *strcpy();
-
- if ((p= malloc((unsigned)strlen(s)+1)) != NULL) {
- return strcpy(p,s);
- }
- else {
- return NULL;
- }
- }
-
- /*
- ** File -- output-file managment package.
- ** Depends on table package.
- */
- #define CURRENT "The current file"
- typedef struct {
- char *name;
- FILE *fp;
- } TABLE;
-
-
- /*
- * initialFile -- create the initial output file (/dev/null).
- */
- FILE *
- initialFile() {
- FILE *fp, *fopen();
- TABLE *addToTable();
-
- if ((fp= fopen("/dev/null","w")) != NULL
- && addToTable("/dev/null",fp) != NULL) {
- return fp;
- }
- else {
- return (FILE *) NULL;
- }
- }
-
- /*
- * initiateFile -- get a file pointer for the named file & save it.
- */
- int
- initiateFile(name) char *name; {
- TABLE *getFromTable(), *addToTable();
- FILE *fp, *fopen();
-
- if (getFromTable(name) != NULL) {
- return 1;
- }
- else if ((fp= fopen(name,"w")) == NULL) {
- return 0;
- }
- else {
- return addToTable(name,fp)? 1: 0;
- }
- }
-
- /*
- * beginFile -- start writing to that file.
- */
- FILE *
- beginFile() {
- TABLE *t, *getFromTable();
-
- if ((t= getFromTable(CURRENT)) != NULL) {
- return t->fp;
- }
- else {
- return NULL;
- }
- }
-
- /*
- * endFile -- stop writing to it.
- */
- FILE *
- endFile() {
- TABLE *getFromTable();
-
- if (getFromTable(CURRENT) != NULL) {
- /* Return the replacement. */
- return getFromTable("/dev/null")->fp;
- }
- else {
- /* Otherwise don't stop using it. */
- return (FILE *) NULL;
- }
- }
-
-
- /*
- *
- */
- #define NFILES 30
- TABLE Table[NFILES];
- static int CurrentFile = -1;
-
- TABLE *
- addToTable(name,fp) char *name; FILE *fp; {
- static int lastLookedAt = 0;
- int i;
- char *strsave();
- TABLE *t, *getFromTable();
-
- if ((t= getFromTable(name)) != NULL) {
- return (TABLE *) t;
- }
- else {
- for (i=lastLookedAt; i < NFILES; i++) {
- if (Table[i].name == NULL) {
- Table[i].name = strsave(name);
- Table[i].fp = fp;
- CurrentFile = i;
- return &Table[i];
- }
- }
- return (TABLE *) NULL;
- }
- }
-
- TABLE *
- getFromTable(name) char *name; {
- int i;
-
- if (streq(name,CURRENT)) {
- return (CurrentFile == -1)? (TABLE *) NULL: &Table[CurrentFile];
- }
- for (i=0; i < NFILES && Table[i].name != NULL; i++) {
- if (streq(Table[i].name,name) != NULL) {
- return &Table[i];
- }
- }
- return (TABLE *) NULL;
- }
-