|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T e
Length: 12946 (0x3292)
Types: TextFile
Names: »extra.c«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
└─⟦c319c2751⟧ »unix3.0/TeX3.0.tar.Z«
└─⟦036c765ac⟧
└─⟦this⟧ »TeX3.0/tex/extra.c«
/*
* Hand-coded routines for C TeX.
* This module should contain any system-dependent code.
*
* This code was written by Tim Morgan, drawing from other Unix
* ports of TeX.
*/
#define CATCHINT /* Catch ^C's */
#define EXTERN /* Actually instantiate globals here */
#include "texd.h"
#ifndef MAXPATHLENGTH /* This is now defined in ../site.h */
#define MAXPATHLENGTH 1024
#endif
/* Various include files we'll need */
#ifdef CATCHINT
#include <signal.h>
#endif
#ifdef BSD
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <fcntl.h>
#else
#include <time.h>
#endif
#if defined(BSD)||defined(SYSV)
#include <sgtty.h>
#endif
static char *texeditvalue = EDITOR;
#ifdef SYSV /* Sys V compatibility */
#define index strchr
#define rindex strrchr
extern int sprintf();
#else
extern char *sprintf();
#endif
/* C library stuff that we're going to use */
#ifndef BSD
#include <string.h>
#else
#include <strings.h>
#endif
extern char *malloc(), *index(), *getenv();
/* Local stuff */
static int gargc;
static char **gargv;
static char texformats[MAXPATHLENGTH]=TEXFORMATS;
static char texinputs[MAXPATHLENGTH]=TEXINPUTS;
static char texfonts[MAXPATHLENGTH]=TEXFONTS;
static char texpool[MAXPATHLENGTH]=TEXPOOL;
static char my_realnameoffile[FILENAMESIZE];
#ifdef CATCHINT
/* If we're catching ^C, come here when one comes in. */
static catchint()
{
interrupt = 1;
(void) signal(SIGINT, catchint);
}
#endif
/* Do the obvious */
get_date_and_time(minutes, day, month, year)
integer *minutes, *day, *month, *year;
{
long clock, time();
struct tm *tmptr, *localtime();
clock = time((long *) 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;
#ifdef CATCHINT
(void) signal(SIGINT, catchint);
#endif
}
#ifdef INITEX
/* Same as in Pascal --- return TRUE if EOF or next char is newline */
eoln(f)
FILE *f;
{
register int c;
if (feof(f)) return(true);
c = getc(f);
if (c != EOF)
(void) ungetc(c, f);
return (c == '\n' || c == EOF);
}
#endif /* INITEX */
static void copy_path(ptr, override)
char *ptr, *override;
{
if (override) {
if (strlen(override) >= MAXPATHLENGTH) {
(void) fprintf(stderr, "Path too long\n");
exit(1);
}
(void) strcpy(ptr, override);
}
}
/* Initialize path variables for loading fonts and things */
setpaths()
{
copy_path(texformats, getenv("TEXFORMATS"));
copy_path(texinputs, getenv("TEXINPUTS"));
copy_path(texfonts, getenv("TEXFONTS"));
copy_path(texpool, getenv("TEXPOOL"));
}
/*
* The following procedure is due to sjc@s1-c.
*
* calledit(filename, fnstart, 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 "fnstart" and "fnlength" the index and
* length of the filename as it appears inside that array.
*
* Ordinarily, this invokes "/usr/ucb/vi". 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 a
* variant copy of "vi" might be:
*
* setenv TEXEDIT "/usr/local/bin/vi +%d %s"
*
*/
calledit(filename, fnstart, fnlength, linenumber)
ASCIIcode *filename;
poolpointer fnstart;
integer fnlength, linenumber;
{
char *temp, *command, c;
int sdone, ddone, i;
sdone = ddone = 0;
filename += fnstart;
/* Close any open input files */
for (i=1; i <= inopen; i++)
(void) fclose(inputfile[i]);
/* Replace default with environment variable if possible.
* We can get away with a simple assignment because we don't call
* getenv() again.
*/
if (NULL != (temp = getenv("TEXEDIT")))
texeditvalue = temp;
/* Make command string containing envvalue, filename, and linenumber */
if (NULL ==
(command = (char *) malloc((unsigned) (strlen(texeditvalue) + fnlength
+ 25)))) {
(void) 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) {
(void) fprintf(stderr,
"! Line number cannot appear twice in editor command\n");
exit(1);
}
(void) sprintf(temp, "%d", linenumber);
while (*temp != '\0')
temp++;
ddone = 1;
break;
case 's':
if (sdone) {
(void) fprintf(stderr,
"! Filename cannot appear twice in editor command\n");
exit(1);
}
i = 0;
while (i < fnlength)
*temp++ = filename[i++] & 0x7F;
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 (system(command))
(void) fprintf(stderr, "! Trouble executing command %s\n", command);
/* Quit, indicating TeX found an error */
exit(1);
}
/*
* Change a Pascal-like filename into a C-like string.
* If running on a non-ASCII system, will have to use xchr[]
* array to convert from internal character set (in the "nameoffile"
* array) into the enternal character set (in "realnameoffile").
* "nameoffile" in TeX is indexed starting at 1, but by the time
* we're called, it has already been bumped up by one.
*/
static packrealnameoffile(prefix, nameoffile)
char *prefix, *nameoffile;
{
register char *cp, *p, *q;
p = prefix;
for (q = my_realnameoffile; p && *p && *p != ':'; *q++ = *p++);
if (prefix && *prefix)
*q++ = '/';
for (cp = nameoffile, p = realnameoffile + 1; *cp != ' ' && *cp;)
#ifdef NONASCII
*q++ = xchr[*p++ = *cp++];
#else
*q++ = (*p++ = *cp++);
#endif
*p = ' ';
*q = '\0';
}
#ifdef BSD
/*
* This code is from Chris Torek:
*
* The following is an internal-use-only routine that makes a core
* dump without any sort of error status. It is used only when
* making a production TeX from a virtex, and is triggered by a magic
* file name requested as \input.
*
* This is what is known in computing circles as a hack.
*/
static void funny_core_dump()
{
int pid, w;
union wait status;
switch (pid = vfork()) {
case -1: /* failed */
perror("vfork");
exit(-1);
/*NOTREACHED*/
case 0: /* child */
(void) signal(SIGQUIT, SIG_DFL);
(void) kill(getpid(), SIGQUIT);
(void) write(2, "how did we get here?\n", 21);
_exit(1);
/*NOTREACHED*/
default: /* parent */
while ((w = wait(&status)) != pid && w != -1)
;
if (status.w_coredump)
exit(0);
(void) write(2, "attempt to dump core failed\n", 28);
exit(1);
}
}
#endif /* BSD */
/* Open an input file f */
Openin(f, pathspec)
FILE **f;
int pathspec;
{
register char *prefix, *nprefix;
register char *cp, *tex_name;
#ifdef BSD
if (pathspec == inputpathspec &&
strncmp(nameoffile+1, "HackyInputFileNameForCoreDump.tex", 33) == 0)
funny_core_dump();
#endif /* BSD */
for (tex_name = &nameoffile[1]; *tex_name == ' '; ++tex_name);
switch (pathspec) {
case inputpathspec:
case readpathspec:
prefix = texinputs;
break;
case fontpathspec:
prefix = texfonts;
break;
case poolpathspec:
prefix = texpool;
break;
case fmtpathspec:
prefix = texformats;
break;
default: /* "Can't" happen */
(void) fprintf(stderr, "INTERNAL CONFUSION---IMPLEMENTATION ERROR\n");
exit(1);
}
if (*tex_name == '/') { /* Absolute pathname-don't do path searching */
for (cp = tex_name; *cp && *cp != ' '; ++cp);
*cp = '\0';
if (*f = fopen(tex_name, "r")) {
(void) strcpy(realnameoffile + 1, tex_name);
(void) strcat(realnameoffile + 1, " ");
if (pathspec == fontpathspec)
tfmtemp = getc(*f); /* Simulate readahead on TFM files */
return (1);
}
return (0);
}
/* Else relative pathname */
while (prefix) {
packrealnameoffile(prefix, tex_name);
*f = fopen(my_realnameoffile, "r");
if (*f) {
(void) strcpy(realnameoffile + 1, my_realnameoffile);
(void) strcat(realnameoffile + 1, " ");
if (pathspec == fontpathspec)
tfmtemp = getc(*f); /* Simulate Pascal readahead */
return (1);
}
nprefix = index(prefix, ':');
if (nprefix)
prefix = nprefix + 1;
else
break;
}
return (0);
}
/* Open an output file f */
Openout(f)
FILE **f;
{
register char *tex_name;
int result;
for (tex_name = &nameoffile[1]; *tex_name == ' '; ++tex_name);
packrealnameoffile((char *) NULL, tex_name);
*f = fopen(my_realnameoffile, "w");
return (*f != NULL);
}
/*
* Read a line of input as efficiently as possible while still
* looking like Pascal.
* Sets last==first and returns FALSE if eof is hit.
* Otherwise, TRUE is returned and either last==first or buffer[last-1]!=' ';
* that is, last == first + length(line except trailing whitespace).
*/
boolean zinputln(f)
FILE *f;
{
register int i;
last = first;
#ifdef BSD
if (f == stdin) clearerr(stdin);
#endif
while ( last < bufsize && ((i = getc(f)) != EOF) && i != '\n') {
#ifdef NONASCII
buffer[last++] = i;
#else
buffer[last++] = (i > 127 || i < 0)?' ':i;
#endif
}
if (i == EOF && last == first)
return(false);
if (i != EOF && i != '\n') {
/* We didn't get whole line because of lack of buffer space */
(void) fprintf(stderr, "\nUnable to read an entire line---bufsize=%d\n",
bufsize);
(void) fprintf(stderr, "Please ask a wizard to enlarge me.\n");
exit(1);
}
buffer[last] = ' ';
if (last >= maxbufstack)
maxbufstack = last; /* Record keeping */
/* Trim trailing whitespace by decrementing "last" */
while (last > first && (buffer[last-1] == ' ' || buffer[last-1] == '\t'))
--last;
/* Now, either last==first or buffer[last-1] != ' ' (or tab) */
/*
* If we're running on a system with ASCII characters like TeX's
* internal character set, we can save some time by not executing
* this loop.
*/
#ifdef NOTASCII
for (i = first; i <= last; i++)
buffer[i] = xord[buffer[i]];
#endif
return(true);
}
/*
* Clear any pending terminal input.
* The usual way to do this in Unix is to switch the terminal to get
* the current tty flags, set RAW mode, then switch back to the original
* setting. If the user isn't in COOKED mode, though, this won't work.
* At least, it leaves his terminal in its original mode.
*/
clearterminal()
{
#ifdef BSD
int arg = FREAD;
(void) ioctl(fileno(stdout), TIOCFLUSH, &arg);
#endif /* BSD */
}
/*
* Cancel any output cancellation (^O) by the user. This is 4.2BSD code.
* Systems which don't have this feature might want to #define wakeupterminal
* to do nothing, rather than call this empty routine, but it's only called
* when about to read from the terminal, so the extra time (compared with
* the human's response time) is minimal.
*/
wakeupterminal()
{
#ifdef BSD
int i = LFLUSHO;
(void) ioctl(fileno(stdout), TIOCLBIC, (struct sgttyb *) &i);
#endif /* BSD */
}
static char *progname = NULL;
/*
* "Open the terminal for input". Actually, copy any command-line
* arguments for processing. If nothing is available, or we've
* been called already (and hence, gargc==0), we return with last==first.
*/
topenin()
{
register int i;
buffer[first] = '\0'; /* So the first strcat will work */
#ifndef INITEX
/* If no format file specified, use progname as the default */
if ((gargc < 2 || gargv[1][0] != '&') && progname != NULL)
(void) sprintf((char *) &buffer[first], "&%s ", progname);
progname = NULL;
#endif /* ! INITEX */
if (gargc > 1) { /* There are command-line arguments */
for (i=1; i<gargc; i++) {
(void) strcat((char *) &buffer[first], gargv[i]);
(void) strcat((char *) &buffer[first], " ");
}
gargc = 0; /* Don't do this again */
}
/* Make last index 1 past the last non-blank character in buffer[] */
for (last=first; buffer[last]; ++last);
for (--last; last >= first && buffer[last] == ' '; --last);
++last;
}
/*
* Get things going under Unix: set up for rescanning the command line,
* then call TeX's main body.
*/
main(argc, argv)
int argc;
char *argv[];
{
#ifndef INITEX
if (readyalready != 314159) {
if ((progname = rindex(argv[0], '/')) == NULL)
progname = argv[0];
else
++progname;
if (strcmp(progname, "virtex") == 0)
progname = NULL;
}
#endif /* ! INITEX */
gargc = argc;
gargv = argv;
texbody();
/*NOTREACHED*/
}
#ifdef DEBUG
getint()
{
int i;
if (fscanf(stdin, "%d", &i)) return(i);
return(0);
}
#endif /* DEBUG */