diff options
Diffstat (limited to 'systems/knuth/local/tex-sparc/ext.c')
-rw-r--r-- | systems/knuth/local/tex-sparc/ext.c | 468 |
1 files changed, 468 insertions, 0 deletions
diff --git a/systems/knuth/local/tex-sparc/ext.c b/systems/knuth/local/tex-sparc/ext.c new file mode 100644 index 0000000000..5d86e6799e --- /dev/null +++ b/systems/knuth/local/tex-sparc/ext.c @@ -0,0 +1,468 @@ +/* external procedures called by TeX */ +#include <sys/signal.h> +#include <sys/time.h> +#include "texpaths.h" /* defines MAXINPATHCHARS, defaultinputpath, etc. */ +#include "h00vars.h" + +/* The following are for closing files */ + +closea(f) + int *f; /* actually, file pointer, but it doesn't matter */ +{ + close1(f); +} + +closeb(f) + int *f; /* actually, file pointer, but it doesn't matter */ +{ + close1(f); +} + +closew(f) + int *f; /* actually, file pointer, but it doesn't matter */ +{ + close1(f); +} + +extern int interrupt; /* To be made nonzero to tell TeX about interrupts */ + +/* +** catchint() +** +** Gets called when the user hits his interrupt key. Sets the global +** "interrupt" nonzero, then sets it up so that the next interrupt will +** also be caught here. +** +*/ + +catchint() +{ + interrupt = 1; + signal(SIGINT,catchint); +} + +/* +** dateandtime(time, day, month, year) +** +** Stores minutes since midnight, current day, month and year into +** *time, *day, *month and *year, respectively. +** +** Also, set things up so that catchint() will get control on interrupts. +** +*/ + +dateandtime(minutes, day, month, year) +int *minutes, *day, *month, *year; +{ + long clock; + struct tm *tmptr, *localtime(); + + clock = time(0); + tmptr = localtime(&clock); + + *minutes = tmptr->tm_hour * 60 + tmptr->tm_min; + *day = tmptr->tm_mday; + *month = tmptr->tm_mon + 1; + *year = tmptr->tm_year + 1900; + signal(SIGINT,catchint); +} + + +/* fixed arrays are used to hold the paths, to avoid any possible problems + involving interaction of malloc and undump */ + +char inputpath[MAXINPATHCHARS] = defaultinputpath; +char fontpath[MAXOTHPATHCHARS] = defaultfontpath; +char formatpath[MAXOTHPATHCHARS] = defaultformatpath; +char poolpath[MAXOTHPATHCHARS] = defaultpoolpath; + +char *getenv(); + +/* + * setpaths is called to set up the arrays inputpath, fontpath, formatpath + * and poolpath as follows: if the user's environment has a value for the + * appropriate value, then use it; otherwise, leave the current value of + * the array (which may be the default path, or it may be the result of + * a call to setpaths on a previous run that was made the subject of + * an undump: this will give the maker of a preloaded TeX the option of + * providing a new set of "default" paths. + * + * Note that we have to copy the string from the environment area, since + * that will change on the next run (which matters if this is for a + * preloaded TeX). + */ +setpaths() +{ + register char *envpath; + + if ((envpath = getenv("TEXINPUTS")) != NULL) + copypath(inputpath,envpath,MAXINPATHCHARS); + if ((envpath = getenv("TEXFONTS")) != NULL) + copypath(fontpath,envpath,MAXOTHPATHCHARS); + if ((envpath = getenv("TEXFORMATS")) != NULL) + copypath(formatpath,envpath,MAXOTHPATHCHARS); + if ((envpath = getenv("TEXPOOL")) != NULL) + copypath(poolpath,envpath,MAXOTHPATHCHARS); +} + +/* + * copypath(s1,s2,n) copies at most n characters (including the null) + * from string s2 to string s1, giving an error message for paths + * that are too long. + */ +copypath(s1,s2,n) + register char *s1,*s2; + register int n; +{ + while ((*s1++ = *s2++) != '\0') + if (--n == 0) { + fprintf(stderr, "! Environment search path is too big\n"); + *--s1 = '\0'; + return; /* let user continue with truncated path */ + } +} + +extern short buffer[],xord[]; /* arrays of 0..255 */ +extern short last,first; /* pointers into buffer */ + +/* + * lineread reads from the Pascal text file with iorec pointer filep + * into buffer[first], buffer[first+1],..., buffer[last-1] (and + * setting "last"). + * Since 8-bit code is in the buffer, the elements are "short", not char. +* Characters are read until a newline is found (which isn't put in the + * buffer) or until the next character would go into buffer[lastlim]. + * The characters need to be translated, so really xord[c] is put into + * the buffer when c is read. + * If end-of-file is encountered, the funit field of *filep is set + * appropriately. + */ +lineread(filep, lastlim) +struct iorec *filep; +int lastlim; +{ + register c; + register short *cs; /* pointer into buffer where next char goes */ + register FILE *iop; /* stdio-style FILE pointer */ + int l; /* how many more chars are allowed before buffer overflow */ + short *bf; /* hold address of buffer[first] */ + + iop = filep->fbuf; + bf = cs = &(buffer[first]); + l = lastlim-first; + /* overflow when next char would go into buffer[lastlim] */ + while (--l>=0 && (c = getc(iop)) != EOF && c!='\n') + *cs++ = xord[c]; + if (c == EOF) + filep->funit |= EOFF; /* we hit end-of-file */ + last = first+cs-bf; +} + +#define filenamesize 1024 /* should agree with initex.ch */ +extern char nameoffile[],realnameoffile[]; /* these have size filenamesize */ + +/* + * testaccess(amode,filepath) + * + * Test whether or not the file whose name is in the global nameoffile + * can be opened for reading (if mode=READACCESS) + * or writing (if mode=WRITEACCESS). + * + * The filepath argument is one of the ...FILEPATH constants defined below. + * If the filename given in nameoffile does not begin with '/', we try + * prepending all the ':'-separated areanames in the appropriate path to the + * filename until access can be made, if it ever can. + * + * The realnameoffile global array will contain the name that yielded an + * access success. + */ + +#define READACCESS 4 +#define WRITEACCESS 2 + +#define NOFILEPATH 0 +#define INPUTFILEPATH 1 +#define READFILEPATH 2 +#define FONTFILEPATH 3 +#define FORMATFILEPATH 4 +#define POOLFILEPATH 5 + +bool +testaccess(amode,filepath) + int amode,filepath; +{ + register bool ok; + register char *p; + char *curpathplace; + int f; + + switch(filepath) { + case NOFILEPATH: curpathplace = NULL; break; + case INPUTFILEPATH: case READFILEPATH: + curpathplace = inputpath; break; + case FONTFILEPATH: curpathplace = fontpath; break; + case FORMATFILEPATH: curpathplace = formatpath; break; + case POOLFILEPATH: curpathplace = poolpath; break; + } + if (nameoffile[0]=='/') /* file name has absolute path */ + curpathplace = NULL; + do { + packrealnameoffile(&curpathplace); + if (amode==READACCESS) + /* use system call "access" to see if we could read it */ + if (access(realnameoffile,READACCESS)==0) ok = TRUE; + else ok = FALSE; + else { + /* WRITEACCESS: use creat to see if we could create it, but close + the file again if we're OK, to let pc open it for real */ + f = creat(realnameoffile,0666); + if (f>=0) ok = TRUE; + else ok = FALSE; + if (ok) + close(f); + } + } while (!ok && curpathplace != NULL); + if (ok) { /* pad realnameoffile with blanks, as Pascal wants */ + for (p = realnameoffile; *p != '\0'; p++) + /* nothing: find end of string */ ; + while (p < &(realnameoffile[filenamesize])) + *p++ = ' '; + } + return (ok); +} + +/* + * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp, + * followed by '/', followed by the characters in nameoffile up until the + * first blank there, and finally a '\0'. The cpp pointer is left pointing + * at the next directory in the path. + * But: if *cpp == NULL, then we are supposed to use nameoffile as is. + */ +packrealnameoffile(cpp) + char **cpp; +{ + register char *p,*realname; + + realname = realnameoffile; + if ((p = *cpp)!=NULL) { + while ((*p != ':') && (*p != '\0')) { + *realname++ = *p++; + if (realname == &(realnameoffile[filenamesize-1])) + break; + } + if (*p == '\0') *cpp = NULL; /* at end of path now */ + else *cpp = p+1; /* else get past ':' */ + *realname++ = '/'; /* separate the area from the name to follow */ + } + /* now append nameoffile to realname... */ + p = nameoffile; + while (*p != ' ') { + if (realname >= &(realnameoffile[filenamesize-1])) { + fprintf(stderr,"! Full file name is too long\n"); + break; + } + *realname++ = *p++; + } + *realname = '\0'; +} + +/* +** testeof(filep) +** +** Test whether or not the Pascal text file with iorec pointer filep +** has reached end-of-file (when the only I/O on it is done with +** lineread, above). +** We may have to read the next character and unget it to see if perhaps +** the end-of-file is next. +*/ + +bool +testeof(filep) +register struct iorec *filep; +{ + register char c; + register FILE *iop; /* stdio-style FILE pointer */ + if (filep->funit & EOFF) + return(TRUE); + else { /* check to see if next is EOF */ + iop = filep->fbuf; + c = getc(iop); + if (c == EOF) + return(TRUE); + else { + ungetc(c,iop); + return(FALSE); + } + } +} + + +/* +** writedvi(a,b) +** +** writedvi is called to write dvibuf[a..b] to dvifile +** Unfortunately, dvibuf is declared as eight_bits, which in our +** implementation means that two bytes are taken by each entry. +** We only want to output the low order (first) byte of each pair. +*/ +extern struct iorec dvifile; +extern short dvibuf[]; +writedvi (a,b) + int a,b; +{ + register short *ptr,*final; + register FILE *iop; + + iop=dvifile.fbuf; + ptr= &(dvibuf[a]); + final= &(dvibuf[b]); + while (ptr<=final) { + putc((char) (*ptr & 0377), iop); + ptr += 1; + } + /* Note: The above code used to be machine dependent. By changing + * the declarations from "char *" to "short *" we get the machine + * to do its own byte ordering of the de-reference of "ptr" above. + * Then we AND off the low bits (now that it's been pulled from + * memory correctly) and cast it into a "char" for putc(). + * --Peter Kessler's idea; explanation, AND, cast a la clp. + */ +} + + +/* +** close1(filep) +** close1 does the proper things to pc's runtime system file data structure +** to close a file +*/ +close1(filep) + + register struct iorec *filep; +{ + register struct iorec *next; + + if (filep->fbuf != 0) { + if ((filep->funit & FDEF) == 0) { + next = (struct iorec *) &_fchain; + while (next->fchain != FILNIL + && next->fchain != filep) + next = next->fchain; + if (next->fchain != FILNIL) + next->fchain = next->fchain->fchain; + + if (filep->fblk > PREDEF) { + fflush(filep->fbuf); + setbuf(filep->fbuf, NULL); + } + fclose(filep->fbuf); + if (ferror(filep->fbuf)) { +/* ERROR and PERROR no longer exist in Pascal library; TeX doesn't know + what to do with them anyway! So I'm commenting this out... don 7/18/92 */ +/* ERROR("%s: Close failed\n", + filep->pfname); */ + return; + } + filep->fbuf=0; + } + if ((filep->funit & TEMP) != 0 && + unlink(filep->pfname)) { +/* PERROR("Could not remove ", filep->pfname); */ + return; + } + } +} + +/* +** The following procedure is due to sjc@s1-c. +** (with mods for 8-bit changes --- don, Sep 89) +** +** calledit(filename, fnlength, linenumber) +** +** TeX82 can call this to implement the 'e' feature in error-recovery +** mode, invoking a text editor on the erroneous source file. +** +** You should pass to "filename" the first character of the packed array +** containing the filename, and to "fnlength" the size of the filename. +** +** New problem (8-bit mod): need to add 128 to all characters of filename! +** +** Ordinarily, this invokes emacs. If you want a different +** editor, create a shell environment variable TEXEDIT containing +** the string that invokes that editor, with "%s" indicating where +** the filename goes and "%d" indicating where the decimal +** linenumber (if any) goes. For example, a TEXEDIT string for "vi" might be: +** +** setenv TEXEDIT "/usr/bin/vi +%d %s" +** +*/ + + char dvalue[] = "emacs +%d %s"; + char *texeditvalue = &dvalue[0]; + + calledit(filename, fnlength, linenumber) + char *filename; + int fnlength, linenumber; + { + char *temp, *command, c; + int sdone, ddone, i; + + sdone = ddone = 0; + + /* Replace default with environment variable if possible. */ + if (NULL != (temp = (char *) getenv("TEXEDIT"))) + texeditvalue = temp; + + /* Make command string containing envvalue, filename, and linenumber */ + if (NULL == + (command = (char *) malloc(strlen(texeditvalue) + fnlength + 25))) { + fprintf(stderr, "! Not enough memory to issue editor command\n"); + exit(1); + } + temp = command; + while ((c = *texeditvalue++) != '\0') { + if (c == '%') { + switch (c = *texeditvalue++) { + case 'd': + if (ddone) { + fprintf(stderr, + "! Line number cannot appear twice in editor command\n"); + exit(1); + } + sprintf(temp, "%d", linenumber); + while (*temp != '\0') + temp++; + ddone = 1; + break; + case 's': + if (sdone) { + fprintf(stderr, + "! Filename cannot appear twice in editor command\n"); + exit(1); + } + i = 0; + while (i < fnlength) + *temp++ = filename[i++] ^ 0x80; /* don's change */ + sdone = 1; + break; + case '\0': + *temp++ = '%'; + texeditvalue--; /* Back up to \0 to force termination. */ + break; + default: + *temp++ = '%'; + *temp++ = c; + break; + } + } + else + *temp++ = c; + } + *temp = '\0'; + + /* Execute command. */ + if (0 != system(command)) + fprintf(stderr, "! Trouble executing command %s\n", command); + + /* Quit, indicating TeX had found an error before you typed "e". */ + exit(1); + } |