Vile 06/17 - vi feel-alike (multi-window)
Paul Fox
pgf at cayman.COM
Sat Jun 8 08:09:32 AEST 1991
#!/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 at cayman.com, (617)494-1999
Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
More information about the Alt.sources
mailing list