pgf@cayman.COM (Paul Fox) (06/08/91)
#!/bin/sh # this is vileshar.06 (part 6 of Vile) # do not concatenate these parts, unpack them in order with /bin/sh # file evar.h continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 6; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 echo 'x - continuing file evar.h' sed 's/^X//' << 'SHAR_EOF' >> 'evar.h' && X /* list of recognized environment variables */ X char *envars[] = { X "fillcol", /* current fill column */ X "pagelen", /* number of lines used by editor */ X "curcol", /* current column pos of cursor */ X "curline", /* current line in file */ X "ram", /* ram in use by malloc */ X "flicker", /* flicker supression */ X "curwidth", /* current screen width */ X "cbufname", /* current buffer name */ X "cfname", /* current file name */ X "sres", /* current screen resolution */ X "debug", /* macro debugging */ X "status", /* returns the status of the last command */ X "palette", /* current palette string */ X "asave", /* # of chars between auto-saves */ X "acount", /* # of chars until next auto-save */ X "lastkey", /* last keyboard char struck */ X "curchar", /* current character under the cursor */ X "discmd", /* display commands on command line */ X "version", /* current version number */ X "progname", /* returns current prog name - "vile" */ X "seed", /* current random number seed */ X "disinp", /* display command line input characters */ X "wline", /* # of lines in current window */ X "cwline", /* current screen line in window */ X "target", /* target for line moves */ X "search", /* search pattern */ X "replace", /* replacement pattern */ X "match", /* last matched magic pattern */ X "kill", /* kill buffer (read only) */ X "cmode", /* mode of current buffer */ X "gmode", /* global modes */ X "tpause", /* length to pause for paren matching */ X "pending", /* type ahead pending flag */ X "lwidth", /* width of current line */ X "line", /* text of current line */ }; X #define NEVARS sizeof(envars) / sizeof(char *) X /* and its preprocesor definitions */ X #define EVFILLCOL 0 #define EVPAGELEN 1 #define EVCURCOL 2 #define EVCURLINE 3 #define EVRAM 4 #define EVFLICKER 5 #define EVCURWIDTH 6 #define EVCBUFNAME 7 #define EVCFNAME 8 #define EVSRES 9 #define EVDEBUG 10 #define EVSTATUS 11 #define EVPALETTE 12 #define EVASAVE 13 #define EVACOUNT 14 #define EVLASTKEY 15 #define EVCURCHAR 16 #define EVDISCMD 17 #define EVVERSION 18 #define EVPROGNAME 19 #define EVSEED 20 #define EVDISINP 21 #define EVWLINE 22 #define EVCWLINE 23 #define EVTARGET 24 #define EVSEARCH 25 #define EVREPLACE 26 #define EVMATCH 27 #define EVKILL 28 #define EVCMODE 29 #define EVGMODE 30 #define EVTPAUSE 31 #define EVPENDING 32 #define EVLWIDTH 33 #define EVLINE 34 X /* list of recognized user functions */ X typedef struct UFUNC { X char *f_name; /* name of function */ X int f_type; /* 1 = monamic, 2 = dynamic */ } UFUNC; X #define NILNAMIC 0 #define MONAMIC 1 #define DYNAMIC 2 #define TRINAMIC 3 X UFUNC funcs[] = { X "add", DYNAMIC, /* add two numbers together */ X "sub", DYNAMIC, /* subtraction */ X "tim", DYNAMIC, /* multiplication */ X "div", DYNAMIC, /* division */ X "mod", DYNAMIC, /* mod */ X "neg", MONAMIC, /* negate */ X "cat", DYNAMIC, /* concatinate string */ X "lef", DYNAMIC, /* left string(string, len) */ X "rig", DYNAMIC, /* right string(string, pos) */ X "mid", TRINAMIC, /* mid string(string, pos, len) */ X "not", MONAMIC, /* logical not */ X "equ", DYNAMIC, /* logical equality check */ X "les", DYNAMIC, /* logical less than */ X "gre", DYNAMIC, /* logical greater than */ X "seq", DYNAMIC, /* string logical equality check */ X "sle", DYNAMIC, /* string logical less than */ X "sgr", DYNAMIC, /* string logical greater than */ X "ind", MONAMIC, /* evaluate indirect value */ X "and", DYNAMIC, /* logical and */ X "or", DYNAMIC, /* logical or */ X "len", MONAMIC, /* string length */ X "upp", MONAMIC, /* uppercase string */ X "low", MONAMIC, /* lower case string */ X "tru", MONAMIC, /* Truth of the universe logical test */ X "asc", MONAMIC, /* char to integer conversion */ X "chr", MONAMIC, /* integer to char conversion */ X "gtk", NILNAMIC, /* get 1 charater */ X "rnd", MONAMIC, /* get a random number */ X "abs", MONAMIC, /* absolute value of a number */ X "sin", DYNAMIC, /* find the index of one string in another */ X "env", MONAMIC, /* retrieve a system environment var */ X "bin", MONAMIC, /* loopup what function name is bound to a key */ }; X #define NFUNCS sizeof(funcs) / sizeof(UFUNC) X /* and its preprocesor definitions */ X #define UFADD 0 #define UFSUB 1 #define UFTIMES 2 #define UFDIV 3 #define UFMOD 4 #define UFNEG 5 #define UFCAT 6 #define UFLEFT 7 #define UFRIGHT 8 #define UFMID 9 #define UFNOT 10 #define UFEQUAL 11 #define UFLESS 12 #define UFGREATER 13 #define UFSEQUAL 14 #define UFSLESS 15 #define UFSGREAT 16 #define UFIND 17 #define UFAND 18 #define UFOR 19 #define UFLENGTH 20 #define UFUPPER 21 #define UFLOWER 22 #define UFTRUTH 23 #define UFASCII 24 #define UFCHR 25 #define UFGTKEY 26 #define UFRND 27 #define UFABS 28 #define UFSINDEX 29 #define UFENV 30 #define UFBIND 31 X #endif SHAR_EOF echo 'File evar.h is complete' && chmod 0444 evar.h || echo 'restore of evar.h failed' Wc_c="`wc -c < 'evar.h'`" test 5247 -eq "$Wc_c" || echo 'evar.h: original size 5247, current size' "$Wc_c" # ============= exec.c ============== echo 'x - extracting exec.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'exec.c' && /* This file is for functions dealing with execution of X commands, command lines, buffers, files and startup files X X written 1986 by Daniel Lawrence */ X #include <stdio.h> #include "estruct.h" #include "edef.h" X /* namedcmd: execute a named command even if it is not bound */ X namedcmd(f, n) int f, n; { X char *fnp; /* ptr to the name of the cmd to exec */ X LINE *fromline; /* first linespec */ X LINE *toline; /* second linespec */ X char lspec[NLINE]; X int cpos = 0; X int s,c,isdfl,zero,flags; X char *kbd_engl(); X CMDFUNC *cfp; /* function to execute */ X extern CMDFUNC f_gomark; X X /* prompt the user to type a named command */ X mlwrite(": "); X X /* and now get the function name to execute */ #if NeWS X newsimmediateon() ; #endif X X while(1) { X c = tgetc(); X if (c == '\r') { X lspec[cpos] = 0; X fnp = NULL; X break; X } else if (c == kcod2key(abortc)) { /* Bell, abort */ X isabortc: X lspec[0] = '\0'; X return FALSE; X } else if (isbackspace(c)) { X if (cpos != 0) { X TTputc('\b'); X TTputc(' '); X TTputc('\b'); X --ttcol; X --cpos; X } else { X lspec[0] = '\0'; X lineinput = FALSE; X return FALSE; X } X X } else if (c == kcod2key(killc)) { /* ^U, kill */ X iskillc: X while (cpos != 0) { X TTputc('\b'); X TTputc(' '); X TTputc('\b'); X --cpos; X --ttcol; X } X } else if (islinespecchar(c) || X /* special test for 'a style mark references */ X (cpos > 0 && X lspec[cpos-1] == '\'' && X (islower(c) || (c == '\'') ) X ) X ) { X lspec[cpos++] = c; X TTputc(c); X ++ttcol; X } else { X int status; X tungetc(c); X lspec[cpos] = 0; X status = kbd_engl_stat(&fnp); X if (status == TRUE) { X break; X } else if (status == SORTOFTRUE) { X fnp = NULL; X continue; X } else { X return status; X } X } X TTflush(); X } X X /* parse the accumulated lspec */ X if (rangespec(lspec,&fromline,&toline,&isdfl,&zero) != TRUE) { X mlwrite("[Improper line range]"); X return FALSE; X } X X /* if range given, and it wasn't "0" and the buffer's empty */ X if (!isdfl && !zero && (lforw(curbp->b_linep) == curbp->b_linep)) { X mlwrite("[No range possible in empty buffer]", fnp); X return FALSE; X } X #if NeWS X newsimmediateoff() ; #endif X X /* did we get a name? */ X if (fnp == NULL) { X if (isdfl) { /* no range, no function */ X mlwrite("[No such function]"); X return FALSE; X } else { /* range, no function */ X cfp = &f_gomark; X fnp = ""; X } X } else if ((cfp = engl2fnc(fnp)) == NULL) { /* bad function */ X mlwrite("[No such function %s]",fnp); X return FALSE; X } X flags = cfp->c_flags; X X /* bad arguments? */ #ifdef EXRC_FILES seems like we need one more check here -- is it from a .exrc file? X cmd not ok in .exrc empty file X if (!(flags & EXRCOK) && (lforw(curbp->b_linep) == curbp->b_linep)) { X mlwrite("[Can't use the \"%s\" command in a %s file.]", X cmdnames[cmdidx].name, EXRC); X return FALSE; X } #endif X X /* was: if (!(flags & (ZERO | EXRCOK)) && fromline == NULL ) { */ X if (zero) { X extern CMDFUNC f_lineputafter, f_opendown, f_insfile; X extern CMDFUNC f_lineputbefore, f_openup; X if (!(flags & ZERO)) { X mlwrite("[Can't use address 0 with \"%s\" command]", fnp); X return FALSE; X } X /* we're positioned at fromline == curbp->b_linep, so commands X must be willing to go _down_ from there. Seems easiest X to special case the commands that prefer going up */ X if (cfp == &f_insfile) { X /* works okay -- acts down normally */ X } else if (cfp == &f_lineputafter) { X cfp = &f_lineputbefore; X fromline = lforw(fromline); X } else if (cfp == &f_opendown) { X cfp = &f_openup; X fromline = lforw(fromline); X } else { X mlwrite("[Configuration error: ZERO]"); X return FALSE; X } X flags = cfp->c_flags; X toline = fromline; X } X X /* if we're not supposed to have a line no., and the line no. isn't X the current line, and there's more than one line */ X if (!(flags & FROM) && fromline != curwp->w_dotp && X (lforw(curbp->b_linep) != curbp->b_linep) && X (lforw(lforw(curbp->b_linep)) != curbp->b_linep) ) { X mlwrite("[Can't use address with \"%s\" command.]", fnp); X return FALSE; X } X /* if we're not supposed to have a second line no., and the line no. X isn't the same as the first line no., and there's more than X one line */ X if (!(flags & TO) && toline != fromline && X (lforw(curbp->b_linep) != curbp->b_linep) && X (lforw(lforw(curbp->b_linep)) != curbp->b_linep) ) { X mlwrite("[Can't use a range with \"%s\" command.]", fnp); X return FALSE; X } #ifdef NEEDED X if (!(flags & EXTRA) && *scan) { X mlwrite("[Extra characters after \"%s\" command.]", X cmdnames[cmdidx].name); X return FALSE; X } #endif #ifdef NEEDED X if ((flags & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!'))) { X build = scan; #ifndef CRUNCH /* what is this for? -pgf */ X if ((flags & PLUS) && *build == '+') { X while (*build && !(isspace(*build))) { X build++; X } X while (*build && isspace(*build)) { X build++; X } X } #endif /* not CRUNCH */ X for (; *build; build++) { X if (isspace(*build)) { X mlwrite("[Too many %s to \"%s\" command.]", X (flags & XFILE) ? "filenames" : "arguments", X cmdnames[cmdidx].name); X return FALSE; X } X } X } #endif /* NEEDED */ X X /* some commands have special default ranges */ X if (isdfl) { X if (flags & DFLALL) { X extern CMDFUNC f_operwrite, f_filewrite, f_operglobals, X f_globals, f_opervglobals, f_vglobals; X if (cfp == &f_operwrite) { X cfp = &f_filewrite; #if GLOBALS X } else if (cfp == &f_operglobals) { X cfp = &f_globals; X } else if (cfp == &f_opervglobals) { X cfp = &f_vglobals; #endif X } else { X mlwrite("[Configuration error: DFLALL]"); X return FALSE; X } X } else if (flags & DFLNONE) { X extern CMDFUNC f_operfilter, f_spawn; X if (cfp == &f_operfilter) { X cfp = &f_spawn; X setmark(); /* not that it matters */ X } else { X mlwrite("[Configuration error: DFLNONE]"); X return FALSE; X } X fromline = toline = NULL; X } X } X #ifdef NEEDED X /* write a newline if called from visual mode */ X if ((flags & NL) && !exmode /* && !exwrote */) { X TTputc('\n'); X /* exrefresh(); */ X } #endif X X if (toline || fromline) { /* assume it's an absolute motion */ X /* we could probably do better */ X curwp->w_ldmkp = curwp->w_dotp; X curwp->w_ldmko = curwp->w_doto; X } X if (toline) { X curwp->w_dotp = toline; X firstnonwhite(); X setmark(); X } X if (fromline) { X curwp->w_dotp = fromline; X firstnonwhite(); X if (!toline) X setmark(); X } X X /* and then execute the command */ X isnamedcmd = TRUE; X havemotion = &f_gomark; X fulllineregions = TRUE; X X s = execute(cfp,f,n); X X havemotion = NULL; X isnamedcmd = FALSE; X fulllineregions = FALSE; X X return s; } X /* parse an ex-style line spec -- code culled from elvis, file ex.c, by X Steve Kirkendall */ char * linespec(s, markptr) register char *s; /* start of the line specifier */ LINE **markptr; /* where to store the mark's value */ { X long num; X LINE *lp; /* where the linespec takes us */ X register char *t; X int status; X X setmark(); X lp = NULL; X X /* parse each ;-delimited clause of this linespec */ X do X { X /* skip an initial ';', if any */ X if (*s == ';') X s++; X X /* skip leading spaces */ X while (isspace(*s)) X s++; X X /* dot means current position */ X if (*s == '.') { X s++; X lp = curwp->w_dotp; X } else if (*s == '$') { /* '$' means the last line */ X s++; X status = gotoeob(TRUE,1); X if (status) lp = curwp->w_dotp; X } else if (isdigit(*s)) { X /* digit means an absolute line number */ X for (num = 0; isdigit(*s); s++) { X num = num * 10 + *s - '0'; X } X status = gotoline(TRUE,num); X if (status) lp = curwp->w_dotp; X } else if (*s == '\'') { X /* appostrophe means go to a set mark */ X s++; X status = gonmmark(*s); X if (status) lp = curwp->w_dotp; X s++; X } #if PATTERNS X else if (*s == '/' || *s == '?') { /* slash means do a search */ X /* put a '\0' at the end of the search pattern */ X t = parseptrn(s); X X /* search for the pattern */ X lp &= ~(BLKSIZE - 1); X if (*s == '/') { X pfetch(markline(lp)); X if (plen > 0) X lp += plen - 1; X lp = m_fsrch(lp, s); X } else { X lp = m_bsrch(lp, s); X } X X /* adjust command string pointer */ X s = t; X } #endif X X /* if linespec was faulty, quit now */ X if (!lp) { X *markptr = lp; X swapmark(); X return s; X } X X /* maybe add an offset */ X t = s; X if (*t == '-' || *t == '+') { X s++; X for (num = 0; *s >= '0' && *s <= '9'; s++) { X num = num * 10 + *s - '0'; X } X if (num == 0) X num = 1; X forwline(TRUE, (*t == '+') ? num : -num); X lp = curwp->w_dotp; X } X } while (*s == ';' || *s == '+' || *s == '-'); X X *markptr = lp; X swapmark(); X return s; } X /* parse an ex-style line range -- code culled from elvis, file ex.c, by X Steve Kirkendall */ rangespec(specp,fromlinep,tolinep,isdefaultp,zerop) char *specp; /* string containing a line range */ LINE **fromlinep; /* first linespec */ LINE **tolinep; /* second linespec */ int *isdefaultp; int *zerop; { X register char *scan; /* used to scan thru specp */ X LINE *fromline; /* first linespec */ X LINE *toline; /* second linespec */ X int noaddrallowed; X X *zerop = FALSE; X X /* ignore command lines that start with a double-quote */ X if (*specp == '"') { X *fromlinep = *tolinep = curwp->w_dotp; X return TRUE; X } X X /* permit extra colons at the start of the line */ X while (isspace(*specp) || *specp == ':') { X specp++; X } X X /* parse the line specifier */ X scan = specp; X if (lforw(curbp->b_linep) == curbp->b_linep) { X fromline = toline = NULL; X } else if (*scan == '%') { X /* '%' means all lines */ X fromline = lforw(curbp->b_linep); X toline = lback(curbp->b_linep); X scan++; X } else if (*scan == '0') { X fromline = toline = curbp->b_linep; /* _very_ top of buffer */ X *zerop = TRUE; X scan++; X } else { X scan = linespec(scan, &fromline); X if (!fromline) X fromline = curwp->w_dotp; X toline = fromline; X if (*scan == ',') { X scan++; X scan = linespec(scan, &toline); X } X if (!toline) { X /* faulty line spec -- fault already described */ X dbgwrite("null toline"); X return FALSE; X } X } X X *isdefaultp = (scan == specp); X X /* skip whitespace */ X while (isspace(*scan)) X scan++; X X if (*scan) { X dbgwrite("crud at end %s",specp); X return FALSE; X } X X *fromlinep = fromline; X *tolinep = toline; X X return TRUE; } X /* old namedcmd: execute a named command even if it is not bound */ onamedcmd(f, n) int f, n; /* command arguments [passed through to command executed] */ { X register char *fnp; /* ptr to the name of the cmd to exec */ X char *kbd_engl(); X int s; X X /* prompt the user to type a named command */ X mlwrite(": "); X X /* and now get the function name to execute */ #if NeWS X newsimmediateon() ; #endif X X fnp = kbd_engl(); X #if NeWS X newsimmediateoff() ; #endif X X if (fnp == NULL) { X mlwrite("[No such function]"); X return FALSE; X } X X /* and then execute the command */ X isnamedcmd = TRUE; X s = docmd(fnp,FALSE,f,n); X isnamedcmd = FALSE; X X return s; } X #if NEVER /* execcmd: Execute a command line command by name alone */ execcmd(f, n) int f, n; /* default Flag and Numeric argument */ { X register int status; /* status return */ X char cmdbuf[NSTRING]; /* string holding command to execute */ X X /* get the line wanted */ X cmdbuf[0] = 0; X if ((status = mlreply("cmd: ", cmdbuf, NSTRING)) != TRUE) X return status; X X execlevel = 0; X return docmd(cmdbuf,TRUE,f,n); } #endif X /* docmd: take a passed string as a command line and translate X it to be executed as a command. This function will be X used by execute-command-line and by all source and X startup files. X X format of the command line is: X X {# arg} <command-name> {<argument string(s)>} X */ X docmd(cline,newcle,f,n) char *cline; /* command line to execute */ { X int status; /* return status of function */ X int flags; /* function flags */ X int oldcle; /* old contents of clexec flag */ X char *oldestr; /* original exec string */ X char tkn[NSTRING]; /* next token off of command line */ X CMDFUNC *cfp; X extern CMDFUNC f_godotplus; X X /* if we are scanning and not executing..go back here */ X if (execlevel) X return TRUE; X X oldestr = execstr; /* save last ptr to string to execute */ X execstr = cline; /* and set this one as current */ X X /* first set up the default command values */ X if (newcle == TRUE) { X f = FALSE; X n = 1; X } X X if ((status = macarg(tkn)) != TRUE) { /* and grab the first token */ X execstr = oldestr; X return status; X } X X /* process leadin argument */ X if (toktyp(tkn) != TKCMD) { X f = TRUE; X strcpy(tkn, tokval(tkn)); X n = atoi(tkn); X X /* and now get the command to execute */ X if ((status = macarg(tkn)) != TRUE) { X execstr = oldestr; X return status; X } X } X X /* and match the token to see if it exists */ X if ((cfp = engl2fnc(tkn)) == NULL) { X mlwrite("[No such function %s]",tkn); X execstr = oldestr; X return FALSE; X } X X /* save the arguments and go execute the command */ X oldcle = clexec; /* save old clexec flag */ X clexec = newcle; /* in cline execution */ X status = execute(cfp,f,n); X cmdstatus = status; /* save the status */ X clexec = oldcle; /* restore clexec flag */ X execstr = oldestr; X return status; } X /* token: chop a token off a string X return a pointer past the token */ X char * token(src, tok) char *src, *tok; /* source string, destination token string */ { X register int quotef; /* is the current string quoted? */ X X /* first scan past any whitespace in the source string */ X while (isspace(*src)) X ++src; X X /* scan through the source string */ X quotef = FALSE; X while (*src) { X /* process special characters */ X if (*src == '\\') { X ++src; X if (*src == 0) X break; X switch (*src++) { X case 'r': *tok++ = '\r'; break; X case 'n': *tok++ = '\n'; break; X case 't': *tok++ = '\t'; break; X case 'b': *tok++ = '\b'; break; X case 'f': *tok++ = '\f'; break; X default: *tok++ = *(src-1); X } X } else { X /* check for the end of the token */ X if (quotef) { X if (*src == '"') X break; X } else { X if (*src == ' ' || *src == '\t') X break; X } X X /* set quote mode if qoute found */ X if (*src == '"') X quotef = TRUE; X X /* record the character */ X *tok++ = *src++; X } X } X X /* terminate the token and exit */ X if (*src) X ++src; X *tok = 0; X return src; } X macarg(tok) /* get a macro line argument */ char *tok; /* buffer to place argument */ { X int savcle; /* buffer to store original clexec */ X X savcle = clexec; /* save execution mode */ X clexec = TRUE; /* get the argument */ X /* grab token and advance past */ X execstr = token(execstr, tok); X /* evaluate it */ X strcpy(tok, tokval(tok)); X clexec = savcle; /* restore execution mode */ X return TRUE; } X /* nextarg: get the next argument */ X nextarg(buffer) char *buffer; /* buffer to put token into */ { X /* grab token and advance past */ X execstr = token(execstr, buffer); X /* evaluate it */ X strcpy(buffer, tokval(buffer)); X return TRUE; } X /* storemac: Set up a macro buffer and flag to store all X executed command lines there */ X storemac(f, n) int f; /* default flag */ int n; /* macro number to use */ { X register struct BUFFER *bp; /* pointer to macro buffer */ X char bname[NBUFN]; /* name of buffer to use */ X X /* must have a numeric argument to this function */ X if (f == FALSE) { X mlwrite("No macro specified"); X return FALSE; X } X X /* range check the macro number */ X if (n < 1 || n > 40) { X mlwrite("[Macro number out of range]"); X return FALSE; X } X X /* construct the macro buffer name */ X strcpy(bname, "[Macro xx]"); X bname[7] = '0' + (n / 10); X bname[8] = '0' + (n % 10); X X /* set up the new macro buffer */ X if ((bp = bfind(bname, OK_CREAT, BFINVS)) == NULL) { X mlwrite("[Cannot create macro]"); X return FALSE; X } X X /* and make sure it is empty */ X bclear(bp); X X /* and set the macro store pointers to it */ X mstore = TRUE; X bstore = bp; X return TRUE; } X #if PROC /* storeproc: Set up a procedure buffer and flag to store all X executed command lines there */ X storeproc(f, n) int f; /* default flag */ int n; /* macro number to use */ { X register struct BUFFER *bp; /* pointer to macro buffer */ X register int status; /* return status */ X char bname[NBUFN]; /* name of buffer to use */ X X /* a numeric argument means its a numbered macro */ X if (f == TRUE) X return storemac(f, n); X X /* get the name of the procedure */ X bname[1] = 0; X if ((status = mlreply("Procedure name: ", &bname[1], NBUFN-2)) != TRUE) X return status; X X /* construct the macro buffer name */ X bname[0] = '['; X strcat(bname, "]"); X X /* set up the new macro buffer */ X if ((bp = bfind(bname, OK_CREAT, BFINVS)) == NULL) { X mlwrite("[Can not create macro]"); X return FALSE; X } X X /* and make sure it is empty */ X bclear(bp); X X /* and set the macro store pointers to it */ X mstore = TRUE; X bstore = bp; X return TRUE; } X /* execproc: Execute a procedure */ X execproc(f, n) int f, n; /* default flag and numeric arg */ { X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X static char obufn[NBUFN+2]; /* name of buffer to execute */ X char bufn[NBUFN+2]; /* name of buffer to execute */ X X /* find out what buffer the user wants to execute */ X if ((status = mlreply("Execute procedure: ", obufn, NBUFN)) != TRUE) X return status; X X /* construct the buffer name */ X bufn[0] = '['; X strcat(bufn, obufn); X strcat(bufn, "]"); X X /* find the pointer to that buffer */ X if ((bp=bfind(bufn, NO_CREAT, 0)) == NULL) { X mlwrite("[No such procedure]"); X return FALSE; X } X X /* and now execute it as asked */ X while (n-- > 0) { X if ((status = dobuf(bp)) != TRUE) X return status; X } X return TRUE; } #endif X #if ! SMALLER /* execbuf: Execute the contents of a buffer of commands */ X execbuf(f, n) int f, n; /* default flag and numeric arg */ { X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X static char bufn[NSTRING]; /* name of buffer to execute */ X X /* find out what buffer the user wants to execute */ X if ((status = mlreply("Execute buffer: ", bufn, NBUFN)) != TRUE) X return status; X X /* find the pointer to that buffer */ X if ((bp=bfind(bufn, NO_CREAT, 0)) == NULL) { X mlwrite("No such buffer"); X return FALSE; X } X X /* and now execute it as asked */ X while (n-- > 0) { X if ((status = dobuf(bp)) != TRUE) X return status; X } X return TRUE; } #endif X /* dobuf: execute the contents of the buffer pointed to X by the passed BP X X Directives start with a "!" and include: X #if SMALLER X !endm End a macro #else X !endm End a macro X !if (cond) conditional execution X !else X !endif X !return Return (terminating current macro) X !goto <label> Jump to a label in the current macro X !force Force macro to continue...even if command fails X !while (cond) Execute a loop if the condition is true X !endwhile X X Line Labels begin with a "*" as the first nonblank char, like: X X *LBL01 #endif X */ X dobuf(bp) BUFFER *bp; /* buffer to execute */ { X register int status; /* status return */ X register LINE *lp; /* pointer to line to execute */ X register LINE *hlp; /* pointer to line header */ X LINE *mp; /* Macro line storage temp */ X int dirnum; /* directive index */ X int linlen; /* length of line to execute */ X int i; /* index */ X int force; /* force TRUE result? */ X WINDOW *wp; /* ptr to windows to scan */ X WHBLOCK *whlist; /* ptr to !WHILE list */ X char *einit; /* initial value of eline */ X char *eline; /* text of line to execute */ #if ! SMALLER X WHBLOCK *scanner; /* ptr during scan */ X register LINE *glp; /* line to goto */ X WHBLOCK *whtemp; /* temporary ptr to a WHBLOCK */ X char tkn[NSTRING]; /* buffer to evaluate an expresion in */ #endif X #if DEBUGM X char *sp; /* temp for building debug string */ X register char *ep; /* ptr to end of outline */ #endif X X /* clear IF level flags/while ptr */ X execlevel = 0; X whlist = NULL; X fulllineregions = FALSE; X havemotion = FALSE; X #if ! SMALLER X scanner = NULL; X /* scan the buffer to execute, building WHILE header blocks */ X hlp = bp->b_linep; X lp = hlp->l_fp; X while (lp != hlp) { X /* scan the current line */ X eline = lp->l_text; X i = lp->l_used; X X /* trim leading whitespace */ X while (i-- > 0 && (*eline == ' ' || *eline == '\t')) X ++eline; X X /* if theres nothing here, don't bother */ X if (i <= 0) X goto nxtscan; X X /* if is a while directive, make a block... */ X if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') { X whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK)); X if (whtemp == NULL) { noram: mlwrite("%%Out of memory during while scan"); failexit: freewhile(scanner); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X whtemp->w_begin = lp; X whtemp->w_type = BTWHILE; X whtemp->w_next = scanner; X scanner = whtemp; X } X X /* if is a BREAK directive, make a block... */ X if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') { X if (scanner == NULL) { X mlwrite("%%!BREAK outside of any !WHILE loop"); X goto failexit; X } X whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK)); X if (whtemp == NULL) X goto noram; X whtemp->w_begin = lp; X whtemp->w_type = BTBREAK; X whtemp->w_next = scanner; X scanner = whtemp; X } X X /* if it is an endwhile directive, record the spot... */ X if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) { X if (scanner == NULL) { X mlwrite("%%!ENDWHILE with no preceding !WHILE in '%s'", X bp->b_bname); X goto failexit; X } X /* move top records from the scanner list to the X whlist until we have moved all BREAK records X and one WHILE record */ X do { X scanner->w_end = lp; X whtemp = whlist; X whlist = scanner; X scanner = scanner->w_next; X whlist->w_next = whtemp; X } while (whlist->w_type == BTBREAK); X } X nxtscan: /* on to the next line */ X lp = lp->l_fp; X } X X /* while and endwhile should match! */ X if (scanner != NULL) { X mlwrite("%%!WHILE with no matching !ENDWHILE in '%s'", X bp->b_bname); X goto failexit; X } #endif X X /* starting at the beginning of the buffer */ X hlp = bp->b_linep; X lp = hlp->l_fp; X while (lp != hlp) { X /* allocate eline and copy macro line to it */ X linlen = lp->l_used; X if ((einit = eline = malloc(linlen+1)) == NULL) { X mlwrite("%%Out of Memory during macro execution"); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X strncpy(eline, lp->l_text, linlen); X eline[linlen] = 0; /* make sure it ends */ X X /* trim leading whitespace */ X while (*eline == ' ' || *eline == '\t') X ++eline; X X /* dump comments and blank lines */ X if (*eline == ';' || *eline == 0) X goto onward; X #if DEBUGM X /* if $debug == TRUE, every line to execute X gets echoed and a key needs to be pressed to continue X ^G will abort the command */ X X if (macbug) { X strcpy(outline, "<<<"); X X /* debug macro name */ X strcat(outline, bp->b_bname); X strcat(outline, ":"); X X /* debug if levels */ X strcat(outline, itoa(execlevel)); X strcat(outline, ":"); X X /* and lastly the line */ X strcat(outline, eline); X strcat(outline, ">>>"); X X /* change all '%' to ':' so mlwrite won't expect arguments */ X sp = outline; X while (*sp) X if (*sp++ == '%') { X /* advance to the end */ X ep = --sp; X while (*ep++) X ; X /* null terminate the string one out */ X *(ep + 1) = 0; X /* copy backwards */ X while(ep-- > sp) X *(ep + 1) = *ep; X X /* and advance sp past the new % */ X sp += 2; X } X X /* write out the debug line */ X mlforce(outline); X update(TRUE); X X /* and get the keystroke */ X if (kbd_key() == abortc) { X mlforce("[Macro aborted]"); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X } #endif X X /* Parse directives here.... */ X dirnum = -1; X if (*eline == '~') { X /* Find out which directive this is */ X ++eline; X for (dirnum = 0; dirnum < NUMDIRS; dirnum++) X if (strncmp(eline, dname[dirnum], X strlen(dname[dirnum])) == 0) X break; X X /* and bitch if it's illegal */ X if (dirnum == NUMDIRS) { X mlwrite("%%Unknown Directive"); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X X /* service only the !ENDM macro here */ X if (dirnum == DENDM) { X mstore = FALSE; X bstore = NULL; X goto onward; X } X X /* restore the original eline....*/ X --eline; X } X X /* if macro store is on, just salt this away */ X if (mstore) { X /* allocate the space for the line */ X linlen = strlen(eline); X if ((mp=lalloc(linlen)) == NULL) { X mlwrite("%%Out of memory while storing macro"); X mstore = FALSE; X return FALSE; X } X X /* copy the text into the new line */ X for (i=0; i<linlen; ++i) X lputc(mp, i, eline[i]); X X /* attach the line to the end of the buffer */ X bstore->b_linep->l_bp->l_fp = mp; X mp->l_bp = bstore->b_linep->l_bp; X bstore->b_linep->l_bp = mp; X mp->l_fp = bstore->b_linep; X goto onward; X } X X X force = FALSE; X X /* dump comments */ X if (*eline == '*') X goto onward; X #if ! SMALLER X /* now, execute directives */ X if (dirnum != -1) { X /* skip past the directive */ X while (*eline && *eline != ' ' && *eline != '\t') X ++eline; X execstr = eline; X X switch (dirnum) { X case DIF: /* IF directive */ X /* grab the value of the logical exp */ X if (execlevel == 0) { X if (macarg(tkn) != TRUE) X goto eexec; X if (stol(tkn) == FALSE) X ++execlevel; X } else X ++execlevel; X goto onward; X X case DWHILE: /* WHILE directive */ X /* grab the value of the logical exp */ X if (execlevel == 0) { X if (macarg(tkn) != TRUE) X goto eexec; X if (stol(tkn) == TRUE) X goto onward; X } X /* drop down and act just like !BREAK */ X X case DBREAK: /* BREAK directive */ X if (dirnum == DBREAK && execlevel) X goto onward; X X /* jump down to the endwhile */ X /* find the right while loop */ X whtemp = whlist; X while (whtemp) { X if (whtemp->w_begin == lp) X break; X whtemp = whtemp->w_next; X } X X if (whtemp == NULL) { X mlwrite("%%Internal While loop error"); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X X /* reset the line pointer back.. */ X lp = whtemp->w_end; X goto onward; X X case DELSE: /* ELSE directive */ X if (execlevel == 1) X --execlevel; X else if (execlevel == 0 ) X ++execlevel; X goto onward; X X case DENDIF: /* ENDIF directive */ X if (execlevel) X --execlevel; X goto onward; X X case DGOTO: /* GOTO directive */ X /* .....only if we are currently executing */ X if (execlevel == 0) { X X /* grab label to jump to */ X eline = token(eline, golabel); X linlen = strlen(golabel); X glp = hlp->l_fp; X while (glp != hlp) { X if (*glp->l_text == '*' && X (strncmp(&glp->l_text[1], golabel, X linlen) == 0)) { X lp = glp; X goto onward; X } X glp = glp->l_fp; X } X mlwrite("%%No such label"); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X goto onward; X X case DRETURN: /* RETURN directive */ X if (execlevel == 0) X goto eexec; X goto onward; X X case DENDWHILE: /* ENDWHILE directive */ X if (execlevel) { X --execlevel; X goto onward; X } else { X /* find the right while loop */ X whtemp = whlist; X while (whtemp) { X if (whtemp->w_type == BTWHILE && X whtemp->w_end == lp) X break; X whtemp = whtemp->w_next; X } X X if (whtemp == NULL) { X mlwrite("%%Internal While loop error"); X freewhile(whlist); X mstore = FALSE; X return FALSE; X } X X /* reset the line pointer back.. */ X lp = whtemp->w_begin->l_bp; X goto onward; X } X X case DFORCE: /* FORCE directive */ X force = TRUE; X X } X } #endif X X /* execute the statement */ X status = docmd(eline,TRUE,FALSE,1); X if (force) /* force the status */ X status = TRUE; X X /* check for a command error */ X if (status != TRUE) { X /* look if buffer is showing */ X wp = wheadp; X while (wp != NULL) { X if (wp->w_bufp == bp) { X /* and point it */ X wp->w_dotp = lp; X wp->w_doto = 0; X wp->w_flag |= WFHARD; X } X wp = wp->w_wndp; X } X /* in any case set the buffer . */ X bp->b_dotp = lp; X bp->b_doto = 0; X free(einit); X execlevel = 0; X mstore = FALSE; X freewhile(whlist); X return status; X } X onward: /* on to the next line */ X free(einit); X lp = lp->l_fp; X } X #if ! SMALLER eexec: /* exit the current function */ #endif X mstore = FALSE; X execlevel = 0; X freewhile(whlist); X return TRUE; } X freewhile(wp) /* free a list of while block pointers */ WHBLOCK *wp; /* head of structure to free */ { X if (wp == NULL) X return; X if (wp->w_next) X freewhile(wp->w_next); X free((char *)wp); } X #if ! SMALLER execfile(f, n) /* execute a series of commands in a file */ int f, n; /* default flag and numeric arg to pass on to file */ { X register int status; /* return status of name query */ X static char ofname[NSTRING]; /* name of file to execute */ X char fname[NSTRING]; /* name of file to execute */ X char *fspec; /* full file spec */ X X if ((status = mlreply("File to execute: ", ofname, NSTRING -1)) != TRUE) X return status; X strcpy(fname,ofname); X #if 1 X /* look up the path for the file */ X fspec = flook(fname, FL_ANYWHERE); X X /* if it isn't around */ X if (fspec == NULL) X return FALSE; X #endif X /* otherwise, execute it */ X while (n-- > 0) X if ((status=dofile(fspec)) != TRUE) X return status; X X return TRUE; } #endif X /* dofile: yank a file into a buffer and execute it X if there are no errors, delete the buffer on exit */ X dofile(fname) char *fname; /* file name to execute */ { X register BUFFER *bp; /* buffer to place file to exeute */ X register int status; /* results of various calls */ X register int odiscmd; X char bname[NBUFN]; /* name of buffer */ X X makename(bname, fname); /* derive the name of the buffer */ X if ((bp = bfind(bname, OK_CREAT, 0)) == NULL) /* get the needed buffer */ X return FALSE; X X bp->b_mode = MDVIEW; /* mark the buffer as read only */ X /* and try to read in the file to execute */ X if ((status = readin(fname, FALSE, bp, TRUE)) != TRUE) { X return status; X } X X /* go execute it! */ X odiscmd = discmd; X discmd = FALSE; X status = dobuf(bp); X discmd = odiscmd; X if (status != TRUE) X return status; X X /* if not displayed, remove the now unneeded buffer and exit */ X if (bp->b_nwnd == 0) X zotbuf(bp); X return TRUE; } X /* cbuf: Execute the contents of a numbered buffer */ X cbuf(f, n, bufnum) int f, n; /* default flag and numeric arg */ int bufnum; /* number of buffer to execute */ { X register BUFFER *bp; /* ptr to buffer to execute */ X register int status; /* status return */ X static char bufname[] = "[Macro xx]"; X X /* make the buffer name */ X bufname[7] = '0' + (bufnum / 10); X bufname[8] = '0' + (bufnum % 10); X X /* find the pointer to that buffer */ X if ((bp=bfind(bufname, NO_CREAT, 0)) == NULL) { X mlwrite("[Macro not defined]"); X return FALSE; X } X X /* and now execute it as asked */ X while (n-- > 0) X if ((status = dobuf(bp)) != TRUE) X return status; X return TRUE; } X cbuf1(f, n) { X cbuf(f, n, 1); } X cbuf2(f, n) { X cbuf(f, n, 2); } X cbuf3(f, n) { X cbuf(f, n, 3); } X cbuf4(f, n) { X cbuf(f, n, 4); } X cbuf5(f, n) { X cbuf(f, n, 5); } X cbuf6(f, n) { X cbuf(f, n, 6); } X cbuf7(f, n) { X cbuf(f, n, 7); } X cbuf8(f, n) { X cbuf(f, n, 8); } X cbuf9(f, n) { X cbuf(f, n, 9); } X cbuf10(f, n) { X cbuf(f, n, 10); } X cbuf11(f, n) { X cbuf(f, n, 11); } X cbuf12(f, n) { X cbuf(f, n, 12); } X cbuf13(f, n) { X cbuf(f, n, 13); } X cbuf14(f, n) { X cbuf(f, n, 14); } X cbuf15(f, n) { X cbuf(f, n, 15); } X cbuf16(f, n) { X cbuf(f, n, 16); } X cbuf17(f, n) { X cbuf(f, n, 17); } X cbuf18(f, n) { X cbuf(f, n, 18); } X cbuf19(f, n) { X cbuf(f, n, 19); } X cbuf20(f, n) { X cbuf(f, n, 20); } X cbuf21(f, n) { X cbuf(f, n, 21); } X cbuf22(f, n) { X cbuf(f, n, 22); } X cbuf23(f, n) { X cbuf(f, n, 23); } X cbuf24(f, n) { X cbuf(f, n, 24); } X cbuf25(f, n) { X cbuf(f, n, 25); } X cbuf26(f, n) { X cbuf(f, n, 26); } X cbuf27(f, n) { X cbuf(f, n, 27); } X cbuf28(f, n) { X cbuf(f, n, 28); } X cbuf29(f, n) { X cbuf(f, n, 29); } X cbuf30(f, n) { X cbuf(f, n, 30); } X cbuf31(f, n) { X cbuf(f, n, 31); } X cbuf32(f, n) { X cbuf(f, n, 32); } X cbuf33(f, n) { X cbuf(f, n, 33); } X cbuf34(f, n) { X cbuf(f, n, 34); } X cbuf35(f, n) { X cbuf(f, n, 35); } X cbuf36(f, n) { X cbuf(f, n, 36); } X cbuf37(f, n) { X cbuf(f, n, 37); } X cbuf38(f, n) { X cbuf(f, n, 38); } X cbuf39(f, n) { X cbuf(f, n, 39); } X cbuf40(f, n) { X cbuf(f, n, 40); } X X SHAR_EOF chmod 0444 exec.c || echo 'restore of exec.c failed' Wc_c="`wc -c < 'exec.c'`" test 32572 -eq "$Wc_c" || echo 'exec.c: original size 32572, current size' "$Wc_c" # ============= file.c ============== echo 'x - extracting file.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'file.c' && /* FILE.C: for MicroEMACS X X The routines in this file handle the reading, writing X and lookup of disk files. All of details about the X reading and writing of the disk are in "fileio.c". X */ X #include <stdio.h> #include "estruct.h" #include "edef.h" X char *strchr(); char *strrchr(); X extern int fileispipe; #if DOSFILES extern int dosfile; #endif X /* X * Read a file into the current X * buffer. This is really easy; all you do it X * find the name of the file, and call the standard X * "read a file into the current buffer" code. X */ fileread(f, n) { X register int s; X static char fname[NFILEN]; X X if ((s=mlreply("Replace with file: ", fname, NFILEN)) != TRUE) X return s; X if ((s = glob(fname)) != TRUE) X return FALSE; X /* we want no errors or complaints, so mark it unchanged */ X curbp->b_flag &= ~BFCHG; X return readin(fname, TRUE, curbp, TRUE); } X /* X * Select a file for editing. X * Look around to see if you can find the X * file in another buffer; if you can find it X * just switch to the buffer. If you cannot find X * the file, create a new buffer, read in the X * text, and switch to the new buffer. X * This is ": e" X */ filefind(f, n) { X static char fname[NFILEN]; /* file user wishes to find */ X char nfname[NFILEN]; X char rnfname[NFILEN]; X register int s; /* status return */ X LINE *lp; X X if (clexec || isnamedcmd) { X if ((s=mlreply("Find file: ", fname, NFILEN)) != TRUE) X return s; X } else { X screen_string(fname,NFILEN,_path); X } X if ((s = glob(fname)) != TRUE) X return FALSE; X strcpy (nfname, fname); #if TAGS X if (othmode & OTH_LAZY) { X extern BUFFER *filesbp; X lp = NULL; X while (flook(nfname, FL_HERE) == NULL) { X rvstrcpy(rnfname, fname); X if (makeflist() == FALSE || !sortsearch(rnfname, X strlen(rnfname), filesbp, FALSE, &lp)) { X /* give up, and try what they asked for */ X strcpy (nfname, fname); X break; X } X rvstrncpy(nfname, lp->l_text, llength(lp)); X } X } #endif X return getfile(nfname, TRUE); } X viewfile(f, n) /* visit a file in VIEW mode */ { X char fname[NFILEN]; /* file user wishes to find */ X register int s; /* status return */ X X fname[0] = 0; X if ((s=mlreply("View file: ", fname, NFILEN)) != TRUE) X return s; X if ((s = glob(fname)) != TRUE) X return FALSE; X s = getfile(fname, FALSE); X if (s == TRUE) { /* if we succeed, put it in view mode */ X curwp->w_bufp->b_mode |= MDVIEW; X markWFMODE(curwp->w_bufp); X } X return s; } X /* X * Insert a file into the current X * buffer. This is really easy; all you do it X * find the name of the file, and call the standard X * "insert a file into the current buffer" code. X */ static char insfname[NFILEN]; X insfile(f, n) { X register int s; X X if (!calledbefore) { X if ((s=mlreply("Insert file: ", insfname, NFILEN)) != TRUE) X return s; X if ((s = glob(insfname)) != TRUE) X return FALSE; X } X if (ukb == 0) X return ifile(insfname,TRUE,NULL); X else X return kifile(insfname); } X #if BEFORE insfiletop(f, n) { X register int s; X if ((s=mlreply("Insert file: ", insfname, NFILEN)) != TRUE) X return s; X if ((s = glob(insfname)) != TRUE) X return FALSE; X curwp->w_dotp = curbp->b_linep; X return ifile(insfname,TRUE,NULL); } #endif X getfile(fname, lockfl) char fname[]; /* file name to find */ int lockfl; /* check the file for locks? */ { X register BUFFER *bp; X register LINE *lp; X register int i; X register int s; X char bname[NBUFN]; /* buffer name to put file */ X #if MSDOS X mklower(fname); /* msdos isn't case sensitive */ #endif X if ((bp=bfind(fname, NO_CREAT, 0)) == NULL) { X /* it's not already here by that buffer name */ X for (bp=bheadp; bp!=NULL; bp=bp->b_bufp) { X /* is it here by that filename? */ X if (strcmp(bp->b_fname, fname)==0) { X swbuffer(bp); X lp = curwp->w_dotp; X i = curwp->w_ntrows/2; X while (i-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_flag |= WFMODE|WFHARD; X if (fname[0] != '!') { X mlwrite("[Old buffer]"); X } else { X if (mlyesno( X "Old command output -- rerun")) { X return readin(fname, lockfl, X curbp, TRUE); X } X } X X return TRUE; X } X } X /* it's not here */ X makename(bname, fname); /* New buffer name. */ X /* make sure the buffer name doesn't exist */ X while ((bp=bfind(bname, NO_CREAT, 0)) != NULL) { X if ( !(bp->b_flag & BFCHG) && X lforw(bp->b_linep) == bp->b_linep ) { X /* empty and unmodiefied -- then its okay X to re-use this buffer */ X bp->b_active = 0; X return readin(fname, lockfl, bp, TRUE) && X swbuffer(bp);; X } X /* old buffer name conflict code */ X unqname(bname,TRUE); X s = mlreply("Will use buffer name: ", bname, NBUFN); X if (s == ABORT) X return s; X if (s == FALSE || bname[0] == 0) X makename(bname, fname); X } X /* okay, we've got a unique name -- create it */ X if (bp==NULL && (bp=bfind(bname, OK_CREAT, 0))==NULL) { X mlwrite("Cannot create buffer"); X return FALSE; X } X /* switch and read it in. */ X strcpy(bp->b_fname, fname); X } X return swbuffer(bp); } X /* X Read file "fname" into a buffer, blowing away any text X found there. Returns the final status of the read. */ X readin(fname, lockfl, bp, mflg) char *fname; /* name of file to read */ int lockfl; /* check for file locks? */ register BUFFER *bp; /* read into this buffer */ int mflg; /* print messages? */ { X register WINDOW *wp; X register int s; X register int nline; X int len; X char *errst; X int flag = 0; #if UNIX X int done_update = FALSE; #endif #if VMALLOC X extern int doverifys; X int odv; #endif X #if FILOCK X if (lockfl && lockchk(fname) == ABORT) X return ABORT; #endif #if CRYPT X s = resetkey(bp); X if (s != TRUE) X return s; #endif X if ((s=bclear(bp)) != TRUE) /* Might be old. */ X return s; X bp->b_flag &= ~(BFINVS|BFCHG); X strcpy(bp->b_fname, fname); X X /* turn off ALL keyboard translation in case we get a dos error */ X TTkclose(); X X if ((s=ffropen(fname)) == FIOERR) /* Hard file open. */ X goto out; X X if (s == FIOFNF) { /* File not found. */ X if (mflg) mlwrite("[New file]"); X goto out; X } X X if (mflg) { X mlwrite("[Reading %s ]", fname); X } X #if UNIX & before X if (fileispipe) X ttclean(TRUE); #endif X /* read the file in */ X nline = 0; #if VMALLOC X /* we really think this stuff is clean... */ X odv = doverifys; X doverifys = 0; #endif X while ((s = ffgetline(&len)) == FIOSUC) { X if (addline(bp,fline,len) != TRUE) { X s = FIOMEM; /* Keep message on the */ X break; /* display. */ X } else { #if UNIX X /* reading from a pipe, and internal? */ X if (fileispipe && !ffhasdata()) { X flag |= WFEDIT; X if (!done_update || bp->b_nwnd > 1) X flag |= WFHARD; X for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { X if (wp->w_bufp == bp) { X wp->w_linep=lforw(bp->b_linep); X wp->w_dotp =lback(bp->b_linep); X wp->w_doto = 0; X wp->w_flag |= flag; X } X } X update(FALSE); X done_update = TRUE; X flag = 0; X } else { X flag |= WFHARD; X } X X } #endif X ++nline; X } #if VMALLOC X doverifys = odv; #endif X bp->b_flag &= ~BFCHG; #if UNIX & before X if (fileispipe == TRUE) { X ttunclean(); X TTflush(); X sgarbf = TRUE; X } #endif #if FINDERR X if (fileispipe == TRUE) { X strncpy(febuff,bp->b_bname,NBUFN); X newfebuff = TRUE; X } #endif X ffclose(); /* Ignore errors. */ #if DOSFILES X if (dosfile && (gmode & MDDOS)) X bp->b_mode |= MDDOS; #endif X if (mflg) X readlinesmsg(nline,s,fname,ffronly(fname)); X X /* set read-only mode for read-only files */ X if (fname[0] == '!' #if RONLYVIEW X || ffronly(fname) #endif X ) { X bp->b_mode |= MDVIEW; X } X X bp->b_active = TRUE; X X /* set C mode for C files */ X if (gmode & MDCMOD) { X char *cp; X cp = &fname[strlen(fname)-2]; X if (cp >= fname && cp[0] == '.' && strchr("chCH",cp[1]) ) { X bp->b_mode |= MDCMOD; X } X } X out: X TTkopen(); /* open the keyboard again */ X for (wp=wheadp; wp!=NULL; wp=wp->w_wndp) { X if (wp->w_bufp == bp) { X wp->w_linep = lforw(bp->b_linep); X wp->w_dotp = lforw(bp->b_linep); X wp->w_doto = 0; X wp->w_mkp = NULL; X wp->w_mko = 0; X wp->w_ldmkp = NULL; X wp->w_ldmko = 0; X wp->w_flag |= WFMODE|WFHARD; X } X } X if (s == FIOERR || s == FIOFNF) { /* False if error. */ #if UNIX X extern int sys_nerr, errno; X extern char *sys_errlist[]; X if (errno > 0 && errno < sys_nerr) X mlwrite("%s: %s",fname,sys_errlist[errno]); #endif X return FALSE; X } #if NeWS X newsreportmodes() ; #endif X return TRUE; } X /* utility routine for no. of lines read */ readlinesmsg(n,s,f,rdonly) { X mlwrite("[%sRead %d line%s from \"%s\"%s]", X (s==FIOERR ? "I/O ERROR, " : (s == FIOMEM ? "OUT OF MEMORY, ":"")), X n, n != 1 ? "s":"", f, rdonly ? " (read-only)":"" ); } X /* X * Take a file name, and from it X * fabricate a buffer name. This routine knows X * about the syntax of file names on the target system. X * I suppose that this information could be put in X * a better place than a line of code. X */ X makename(bname, fname) char bname[]; char fname[]; { X register char *cp2; X register char *lastsl; X X register char *fcp; X register char *bcp; X X fcp = &fname[strlen(fname)]; X /* trim trailing whitespace */ X while (fcp != fname && (fcp[-1] == ' ' || fcp[-1] == '\t' #if UNIX /* trim trailing slashes as well */ X || fcp[-1] == '/' #endif X ) ) X *(--fcp) = '\0'; X fcp = fname; X /* trim leading whitespace */ X while (*fcp == ' ' || *fcp == '\t') X fcp++; X #if AMIGA X while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!='/') X --cp1; #endif #if VMS X while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!=']') X --cp1; #endif #if CPM X while (cp1!=fcp && cp1[-1]!=':') X --cp1; #endif #if MSDOS X while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!='\\'&&cp1[-1]!='/') X --cp1; #endif #if ST520 X while (cp1!=fcp && cp1[-1]!=':' && cp1[-1]!='\\') X --cp1; #endif #if UNIX X bcp = bname; X if (*fcp == '!') { /* then it's a shell command. bname is first word */ X *bcp++ = '!'; X while (isspace(*++fcp)) X ; X while (!isspace(*fcp) && bcp < &bname[NBUFN-1]) X *bcp++ = *fcp++; X *bcp = '\0'; X return; X } X if (lastsl = strrchr(fcp,'/')) { X strncpy(bcp,lastsl+1,NBUFN); X bcp[NBUFN-1] = '\0'; X } else { /* no slashes, use the filename as is */ X strncpy(bcp,fcp,NBUFN); X bcp[NBUFN-1] = '\0'; X } X return; X #else X cp2 = &bname[0]; X while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') X *cp2++ = *cp1++; X *cp2 = 0; #endif } X unqname(name,ok_to_ask) /* make sure a buffer name is unique */ char *name; /* name to check on */ { X register char *sp; X X /* check to see if it is in the buffer list */ X while (bfind(name, 0, NO_CREAT) != NULL) { X X sp = &name[strlen(name)-1]; /* last char */ X if (sp - name >= 2 && sp[-1] == '-') { X if (sp[0] == '9') X sp[0] = 'A'; X else if (sp[0] == 'Z') X goto choosename; X else if (isdigit(sp[0]) || isupper(sp[0])) X sp[0] += 1; X } else if (sp + 2 < &name[NBUFN-1]) { X strcat(sp, "-1"); X } else { X choosename: X if (ok_to_ask) { X do { X mlreply("Choose a unique buffer name: ", X name, NBUFN); X } while (name[0] == '\0'); X } else { /* can't ask, just overwrite end of name */ X sp[-1] = '-'; X sp[0] = '1'; X } X } X } } X /* X * Ask for a file name, and write the X * contents of the current buffer to that file. X */ filewrite(f, n) { X register int s; X static char fname[NFILEN]; X X strncpy(fname, curbp->b_fname, NFILEN); X X /* HACK -- this implies knowledge of how kbd_engl works! */ X if (isnamedcmd && lastkey != '\r') { X if ((s=mlreply("Write to file: ", fname, NFILEN)) != TRUE) X return s; X if ((s = glob(fname)) != TRUE) X return FALSE; X if (strcmp(fname,curbp->b_fname) && X fname[0] != '!' && flook(fname,FL_HERE)) { X if (mlyesno("File exists, okay to overwrite") != TRUE) { X mlwrite("File not written"); X return FALSE; X } X } X } X if ((s=writeout(fname,curbp,TRUE)) == TRUE) { X curbp->b_flag &= ~BFCHG; X markWFMODE(curbp); X } X return s; } X /* X * Save the contents of the current X * buffer in its associatd file. Do nothing X * if nothing has changed (this may be a bug, not a X * feature). Error if there is no remembered file X * name for the buffer. X */ filesave(f, n) { X register int s; X #if its_a_bug X if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ X return TRUE; #endif X if (curbp->b_fname[0] == 0) { /* Must have a name. */ X mlwrite("No file name"); X return FALSE; X } X if ((s=writeout(curbp->b_fname,curbp,TRUE)) == TRUE) { X curbp->b_flag &= ~BFCHG; X markWFMODE(curbp); X } X return s; } X /* X * This function performs the details of file X * writing. Uses the file management routines in the X * "fileio.c" package. The number of lines written is X * displayed. Sadly, it looks inside a LINE; provide X * a macro for this. Most of the grief is error X * checking of some sort. X */ writeout(fn,bp,msgf) char *fn; BUFFER *bp; { X register LINE *lp; /* current line */ X register long numchars; /* # of chars in file */ X REGION region; X X /* starting at the beginning of the buffer */ X lp = lforw(bp->b_linep); X region.r_linep = lp; X region.r_offset = 0; X X /* start counting chars */ X numchars = 0; X while (lp != bp->b_linep) { X numchars += llength(lp) + 1; X lp = lforw(lp); X } X region.r_size = numchars; X #if DOSFILES X dosfile = bp->b_mode & MDDOS; #endif X X return writereg(®ion,fn,msgf); } X writeregion(f,n) { X REGION region; X int s; X static char fname[NFILEN]; SHAR_EOF true || echo 'restore of file.c failed' echo 'End of Vile part 6' echo 'File file.c is continued in part 7' echo 7 > _shar_seq_.tmp exit 0 -- paul fox, pgf@cayman.com, (617)494-1999 Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139