/* X11BSDstuff.c - X11 BSD interface routines for xlisp */ /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */ /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */ /* You may give out copies of this software; for conditions see the */ /* file COPYING included with this distribution. */ /* */ /* Some modifications included from WINTERP */ /* WINTERP 1.0 Copyright 1989 Hewlett-Packard Company (by Niels Mayer).*/ #include #include #include "xlisp.h" #include #include "version.h" #ifdef linux #include #endif /* externals */ extern FILEP tfp; extern LVAL s_breakenable; #ifdef CONDITIONS extern LVAL s_condition_hook; #endif /* CONDITIONS */ /* forward declarations */ LOCAL VOID reset_input _((void)); LOCAL int x11_get_char _((void)); LOCAL int line_available _((void)); /* static variables to protect gc from interrupt */ static int in_gc = 0, gc_interrupt = FALSE; static time_t time_stamp; /* -- local variables */ #define LBSIZE 200 static char lbuf[LBSIZE]; static int lindex; static int lcount; #define nil 0L LOCAL VOID intercatch _((int)), fpecatch _((int)); VOID osinit(name) char *name; { #ifdef linux __setfpucw(0x137F); #endif time_stamp = time((time_t *) 0); disable_interrupts(); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, intercatch); signal(SIGFPE, fpecatch); printf("%s\n", name); printf("XLISP-STAT 2.1 Release %d.%d%s.\n", XLS_MAJOR_RELEASE, XLS_MINOR_RELEASE, XLS_RELEASE_STATUS); printf("Copyright (c) 1989-1994, by Luke Tierney.\n\n"); lposition = 0; lindex = 0; lcount = 0; } VOID osfinish() { CONTEXT cntxt; xlbegin(&cntxt,CF_TOPLEVEL|CF_CLEANUP|CF_BRKLEVEL,(LVAL)1); if (setjmp(cntxt.c_jmpbuf)) exit(0); if (s_breakenable != NULL) setvalue(s_breakenable, NIL); #ifdef CONDITIONS if (s_condition_hook != NULL) setvalue(s_condition_hook, NIL); #endif /* CONDITIONS */ StX11Finish(); } VOID osreset() { reset_input(); if (StHasWindows()) { StGWResetBuffer(); StX11DialogReset(); StX11ReleaseButton(); } in_gc = 0; } VOID xoserror(msg) char *msg; { char line[STRMAX],*p; sprintf(line,"error: %s\n",msg); for (p = line; *p != '\0'; ++p) ostputc(*p); } #ifdef DODO FILEP osaopen(name,mode) char *name,*mode; { return (fopen(name,mode)); } FILEP osbopen(name,mode) char *name,*mode; { char nmode[4]; strcpy(nmode,mode); strcat(nmode,"b"); return (fopen(name,nmode)); } int osclose(fp) FILEP fp; { return (fclose(fp)); } #endif /* DODO */ #ifdef FILETABLE extern VOID gc(); int truename(name, rname) char *name,*rname; { char *cp; char pathbuf[FNAMEMAX+1]; /* copy of path part of name */ char curdir[FNAMEMAX+1]; /* current directory */ char *fname; /* pointer to file name part of name */ /* parse any drive specifier */ /* check for absolute path (good news!) */ if (*name == '/') { strcpy(rname, name); } else { strcpy(pathbuf, name); if ((cp = strrchr(pathbuf, '/')) != NULL) { /* path present */ cp[1] = 0; fname = strrchr(name, '/') + 1; } else { pathbuf[0] = 0; fname = name; } /* get the current directory of the selected drive */ getcwd(curdir, FNAMEMAX); /* peel off "../"s */ while (strncmp(pathbuf, "../", 3) == 0) { if (*curdir == 0) return FALSE; /* already at root */ strcpy(pathbuf, pathbuf+3); if ((cp=strrchr(curdir+1, '/')) != NULL) *cp = 0; /* peel one depth of directories */ else *curdir = 0; /* peeled back to root */ } /* allow for a "./" */ if (strncmp(pathbuf, "./", 2) == 0) strcpy(pathbuf, pathbuf+2); /* final name is /curdir/pathbuf/fname */ if ((int)(strlen(pathbuf)+strlen(curdir)+strlen(fname)+4) > FNAMEMAX) return FALSE; if (*curdir) sprintf(rname, "%s/%s%s", curdir, pathbuf, fname); else sprintf(rname, "/%s%s", pathbuf, fname); } return TRUE; } int getslot() { int i=0; for (; i < FTABSIZE; i++) /* look for available slot */ if (filetab[i].fp == NULL) return i; gc(); /* is this safe??????? */ for (; i < FTABSIZE; i++) /* try again -- maybe one has been freed */ if (filetab[i].fp == NULL) return i; xlfail("too many open files"); return 0; /* never returns */ } FILEP osopen(name, mode) char *name, *mode; { int i=getslot(); char namebuf[FNAMEMAX+1]; FILE *fp; if (!truename((char *)name, namebuf)) strcpy(namebuf, name); /* should not happen */ if ((filetab[i].tname = (char *)malloc(strlen(namebuf)+1)) == NULL) { xlfail("insufficient memory"); } if ((fp = fopen(name,mode)) == NULL) { free(filetab[i].tname); return CLOSED; } filetab[i].fp = fp; strcpy(filetab[i].tname, namebuf); return i; } VOID osclose(f) FILEP f; { if (filetab[f].fp != NULL) fclose(filetab[f].fp); /* remind stdin/stdout/stderr */ if (f>2 && filetab[f].tname != NULL) free(filetab[f].tname); filetab[f].tname = NULL; filetab[f].fp = NULL; } int osmtime(fname, mtime) char *fname; time_t *mtime; { struct stat s; if (stat(fname, &s)) return -1; *mtime = s.st_mtime; return 0; } #endif /* FILETABLE */ #ifdef DODO int osagetc(fp) FILEP fp; { return (getc(fp)); } int osbgetc(fp) FILEP fp; { return (getc(fp)); } int osaputc(ch,fp) int ch; FILEP fp; { return (putc(ch,fp)); } int osbputc(ch,fp) int ch; FILEP fp; { return (putc(ch,fp)); } #endif /* DODO */ LOCAL int xostgetc() { int ch; ch = x11_get_char(); if (ch == '\n') lposition = 0; return(ch); } char *xfgets(s, n, iop) char *s; int n; FILEP iop; { int c; char *cs; cs = s; while (--n > 0 && (c = xostgetc()) != EOF) { *cs++ = c; if (c == '\n') break; } if (c == EOF && cs==s) return(NULL); *cs++ = '\0'; return(s); } /* -- ostgetc - get a character from the terminal */ int ostgetc() { while(--lcount < 0 ) { if ( xfgets(lbuf,LBSIZE,stdin) == NULL ) return( EOF ); lcount = strlen( lbuf ); if (tfp!=CLOSED) OSWRITE(lbuf,1,lcount,tfp); lindex = 0; lposition = 0; } return( lbuf[lindex++] ); } VOID ostputc(ch) int ch; { putchar(ch); if (tfp != CLOSED) OSPUTC(ch,tfp); if (ch == '\n') lposition = 0; else lposition++; } VOID osflush() { lindex = lcount = 0; } VOID osforce(fp) FILEP fp; { #ifdef FILETABLE if (fp == CONSOLE) fflush(stdout); else fflush(filetab[fp].fp); #else if (fp == CONSOLE) fflush(stdout); else fflush(fp); #endif /* FILETABLE */ } VOID oscheck() { } VOID ossymbols() { statsymbols(); } #ifdef DODO VOID osfinit() { statfinit(); } #endif /* DODO */ LOCAL VOID intercatch(arg) int arg; { signal(SIGINT, intercatch); if (in_gc > 0) gc_interrupt = TRUE; else xlsigint(); } LOCAL VOID fpecatch(arg) int arg; { signal(SIGFPE, fpecatch); xlfail("floating point error"); } int max(x, y) int x, y; { return((x > y) ? x : y); } int min(x, y) int x, y; { return((x < y) ? x : y); } VOID set_gc_cursor(on) int on; { if (on) disable_interrupts(); else enable_interrupts(); } VOID disable_interrupts() { in_gc++; } VOID enable_interrupts() { if (gc_interrupt && in_gc == 1) { gc_interrupt = FALSE; in_gc = 0; xlsigint(); } else if (in_gc > 0) in_gc--; } VOID SysBeep(n) int n; { n = n / 10 - 1; do { printf("\007"); } while (n-- > 0); fflush(stdout); } #ifndef CLK_TCK #ifndef HZ #define HZ 60 #endif #define CLK_TCK HZ #endif /* CLK_TCK */ #ifdef NODIFFTIME #ifndef difftime #define difftime(x,y) (((unsigned long) (x)) - ((unsigned long) (y))) #endif #endif unsigned long ticks_per_second() { return((unsigned long)(CLK_TCK)); } unsigned long run_tick_count() { struct tms tm; times(&tm); return((unsigned long) tm.tms_utime + (unsigned long) tm.tms_stime); } unsigned long real_tick_count() { return((unsigned long) (CLK_TCK * difftime(time((time_t *) 0), time_stamp))); } unsigned long system_tick_count() { return((unsigned long) time((time_t *) 0)); } /* The following routines will have to be changed for non-BSD systems. At * present they use a BSD-specific ioctl call as well as file structure * information to determine when terminal input characters are available. * While no characters are available events are processed. * * An alternative polling system can be constructed using alarm or * setitimer. The alarm aproach is used in the S X11 and NeWS drivers. */ #ifdef DODO LOCAL int x11_get_char() { int ch; fflush(stdout); do { StPollEvent(); } while (! char_available()); ch = getchar(); return(ch); } LOCAL int char_available() { FILE *file = stdin; int c = 0; if (file->_cnt > 0) return(TRUE); ioctl(fileno(file), FIONREAD, &c); if (c > 0) return(TRUE); else return(StBlockForInput()); } #endif /* DODO */ static int in_a_line = FALSE; LOCAL VOID reset_input() { in_a_line = FALSE; } LOCAL int x11_get_char() { int ch; fflush(stdout); if (! in_a_line) { do { StPollEvent(); } while (! line_available()); } ch = getchar(); in_a_line = (ch == '\n') ? FALSE : TRUE; return(ch); } LOCAL int line_available() { FILE *file = stdin; int result; fd_set readmask; static struct timeval tv = {0, 0}; static int ndfs = 0; if (ndfs == 0) ndfs = fileno(stdin) + 1; /*** is this right? ***/ FD_ZERO(&readmask); FD_SET(fileno(stdin), &readmask); result = select(ndfs, &readmask, nil, nil, &tv); if (result > 0) return(TRUE); /* *** should merge the select here with the one for blocking ***/ else return(StBlockForInput()); } /* * This routine is used to flush input to the tty during modal dialogs. * The ioctl call seems to do the job on BDS systems but may not exist * (in this form) on other systems. The ifdef is a hack to see if the * call is available. */ VOID StX11FlushStdin() { #ifdef TIOCFLUSH int c = 0; ioctl(fileno(stdin), TIOCFLUSH, &c); #else fflush(stdin); #endif } extern char *getenv(); VOID get_directory(s) char *s; { char *libdir; int n; libdir = getenv("XLISPLIB"); if (libdir == nil) libdir = ""; strcpy(s, libdir); n = strlen(s); if (n > 0 && s[n - 1] != '/') strcat(s, "/"); } int renamebackup(name) char *name; { return(TRUE); } /* xgetwd - builtin function GET-WORKING-DIRECTORY */ LVAL xgetwd() { xllastarg(); if (! getcwd(buf, FNAMEMAX)) return NIL; else return cvstring(buf); } /* xsetwd - builtin function SET-WORKING-DIRECTORY */ LVAL xsetwd() { char *dir = getstring(xlgastring()); xllastarg(); if (chdir(dir)) return NIL; else return s_true; } #ifdef NOMEMMOVE VOID memmove P3C(char *, s1, char *, s2, int, n) { if (s1 < s2) while (n--) *s1++ = *s2++; else { s1 += (n-1); s2 += (n-1); while (n--) *s1-- = *s2--; } } #endif /* NOMEMMOVE */