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