sources-request@mirror.UUCP (01/27/87)
Submitted by: emoryu1!arnold (Arnold D. Robbins) Mod.sources: Volume 8, Issue 2 Archive-name: se/Part02 Here is the second release of the Georgia Tech Screen Editor, 'se'. There were enough changes that a whole new posting is warranted. Major Changes: All Georgia Tech specific stuff removed. It understands window size changes on 4.3BSD and ATT Unix PC/3B1 Support for the shared library on the ATT Unix PC/3B1 Considerable source code reorganization in certain files. Enjoy, Arnold Robbins #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # edit.c # extern.h # m4munge # main.c # makefile # misc.c export PATH; PATH=/bin:$PATH echo shar: extracting "'edit.c'" '(26346 characters)' if test -f 'edit.c' then echo shar: will not over-write existing file "'edit.c'" else cat << \SHAR_EOF > 'edit.c' #ifndef lint static char RCSid[] = "$Header: edit.c,v 1.3 86/07/11 15:11:34 osadr Exp $"; #endif /* * $Log: edit.c,v $ * Revision 1.3 86/07/11 15:11:34 osadr * Removed Georgia Tech specific code. * * Revision 1.2 86/05/27 17:44:56 osadr * Removed flexnames dependancy; PREVLINE[2] --> PREVLN[2]. * Improved the sysname() routine, particularly to use the nodename * member of the utsname structure under System V. * * Revision 1.1 86/05/06 13:37:16 osadr * Initial revision * * */ /* ** edit.c ** ** editor main routine, plus other routines used a lot. */ #include "se.h" #include "extern.h" static char Savknm = DEFAULTNAME; /* saved mark name for < and > */ /* edit --- main routine for screen editor */ edit (argc, argv) int argc; char *argv[]; { int cursav, status, len, cursor; int ckglob (), docmd (), doglob (), doread (); int getlst (), nextln (), prevln (); char lin[MAXLINE], term; watch (); /* display time of day */ #ifdef LOG_USAGE log (); /* log who used the program */ #endif serc (); /* execute commands in ./.serc or $HOME/.serc */ status = OK; while (status == OK && Argno < argc) { strcpy (lin, argv[Argno]); loadstr (lin, Argno, POOPCOL, Ncols); if (lin[0] == '-') { len = strlen (lin) + 1; lin[len - 1] = '\n'; lin[len] = EOS; len = 0; status = doopt (lin, &len); } else { dfltsopt (lin); status = doread (Lastln, lin, NO); } Argno++; } if (status == ERR) { if (Errcode == EHANGUP) hangup (); printverboseerrormessage (); } else Curln = min (1, Lastln); Buffer_changed = NO; First_affected = 1; /* maintained by updscreen & commands */ updscreen (); if (status != ERR) /* leave offending file name or option */ lin[0] = EOS; cursor = 0; /* main command loop */ do { intrpt (); /* discard pending breaks (interrupts) */ if (Lost_lines > GARB_THRESHOLD && (Lastln + Limcnt) / Lost_lines <= GARB_FACTOR) garbage_collect (); mswait (); /* check for pending messages */ Cmdrow = Botrow + 1; /* reset the command line location */ prompt ("cmd>"); getcmd (lin, 0, &cursor, &term); remark (""); /* clear out any error messages */ while (term == CURSOR_UP || term == CURSOR_DOWN || term == CURSOR_SAME) { switch (term) { case CURSOR_UP: if (Curln > 1) Curln--; else Curln = Lastln; break; case CURSOR_DOWN: if (Curln < Lastln) Curln++; else Curln = min (1, Lastln); break; } adjust_window (Curln, Curln); updscreen (); getcmd (lin, 0, &cursor, &term); } prompt (""); /* remove prompt */ cursav = Curln; /* remember it in case of an error */ Errcode = EEGARB; /* default error code for garbage at end */ len = 0; if (getlst (lin, &len, &status) == OK) { if (ckglob (lin, &len, &status) == OK) doglob (lin, &len, &cursav, &status); else if (status != ERR) docmd (lin, len, NO, &status); } if (status == ERR) { if (Errcode == EHANGUP) hangup (); printverboseerrormessage (); Curln = min (cursav, Lastln); } else if (term != FUNNY) { cursor = 0; lin[0] = EOS; } adjust_window (Curln, Curln); updscreen (); } while (status != EOF); clrscreen (); clrbuf (); tflush (); return; } /* getlst --- collect line numbers (if any) at lin[*i], increment i */ int getlst (lin, i, status) char lin[]; int *i, *status; { int num; int getone (); Line2 = 0; for (Nlines = 0; getone (lin, i, &num, status) == OK; ) { Line1 = Line2; Line2 = num; Nlines++; if (lin[*i] != ',' && lin[*i] != ';') break; if (lin[*i] == ';') Curln = num; (*i)++; } if (Nlines > 2) Nlines = 2; if (Nlines <= 1) Line1 = Line2; if (Line1 > Line2) { *status = ERR; Errcode = EBACKWARD; } if (*status != ERR) *status = OK; return (*status); } /* getnum --- convert one term to line number */ int getnum (lin, i, pnum, status) char lin[]; register int *i, *pnum, *status; { int j, ret; int ctoi (), optpat (), ptscan (), knscan (), getkn (); int k; ret = OK; SKIPBL (lin, *i); if (lin[*i] >= Rel_a && lin[*i] <= Rel_z && Absnos == NO) *pnum = Topln - Toprow + lin[*i] - Rel_a; else if (lin[*i] == CURLINE) *pnum = Curln; else if (lin[*i] == PREVLN || lin[*i] == PREVLN2) *pnum = Curln - 1; else if (lin[*i] == LASTLINE) *pnum = Lastln; else if (lin[*i] == SCAN || lin[*i] == BACKSCAN) { int missing_delim = YES; /* see if trailing delim supplied, since command can follow pattern */ for (k = *i + 1; lin[k] != EOS; k++) if (lin[k] == ESCAPE) k++; /* skip esc, loop will skip escaped char */ else if (lin[k] == lin[*i]) { missing_delim = NO; break; } /* else continue */ if (missing_delim == YES) { for (; lin[k] != EOS; k++) ; k--; /* k now at newline */ /* supply trailing delim */ lin[k] = lin[*i]; lin[++k] = '\n'; lin[++k] = EOS; Peekc = SKIP_RIGHT; } if (optpat (lin, i) == ERR) ret = ERR; else if (lin[*i] == SCAN) ret = ptscan (FORWARD, pnum); else ret = ptscan (BACKWARD, pnum); } else if (lin[*i] == SEARCH || lin[*i] == BACKSEARCH) { j = *i; (*i)++; if (getkn (lin, i, &Savknm, Savknm) == ERR) ret = ERR; else if (lin[j] == SEARCH) ret = knscan (FORWARD, pnum); else ret = knscan (BACKWARD, pnum); (*i)--; } else if (isdigit (lin[*i])) { *pnum = ctoi (lin, i); (*i)--; } else if (lin[*i] == TOPLINE) *pnum = Topln; else ret = EOF; if (ret == OK) (*i)++; *status = ret; return (ret); } /* getone --- evaluate one line number expression */ int getone (lin, i, num, status) char lin[]; register int *i, *num, *status; { int pnum, ret; int getnum (); char porm; /* "plus or minus" (sic) */ ret = EOF; /* assume we won't find anything for now */ *num = 0; if (getnum (lin, i, num, status) == OK) /* first term */ { ret = OK; /* to indicate we've seen something */ do { /* + or - terms */ porm = EOS; SKIPBL (lin, *i); if (lin[*i] == '-' || lin[*i] == '+') { porm = lin[*i]; (*i)++; } if (getnum (lin, i, &pnum, status) == OK) if (porm == '-') *num -= pnum; else *num += pnum; if (*status == EOF && porm != EOS) /* trailing + or - */ *status = ERR; } while (*status == OK); } if (*num < 0 || *num > Lastln) /* make sure number is in range */ { *status = ERR; Errcode = EORANGE; } if (*status == ERR) ret = ERR; else *status = ret; return (ret); } #ifndef OLD_SCRATCH #ifndef OLD_GLOB static int special_casing = NO; #endif #endif /* ckglob --- if global prefix, mark lines to be affected */ int ckglob (lin, i, status) char lin[]; int *i, *status; { register int line, tmp; int usepat, usemark; int defalt (), match (), optpat (), getkn (); register LINEDESC *k; LINEDESC *gettxt (), *getind (); *status = OK; usepat = EOF; usemark = EOF; #ifndef OLD_SCRATCH #ifndef OLD_GLOB if ( /* g/^/m0 or g/$/m0 -- special case the pathological */ /* cases in order to save time */ (lin[*i] == GLOBAL || lin[*i] == UCGLOBAL) && (lin[*i + 1] == lin[*i + 3]) && (lin[*i + 2] == '^' || lin[*i + 2] == '$') && (lin[*i + 4] == MOVECOM || lin[*i + 4] == UCMOVECOM) && (lin[*i + 5] == '0' && lin[*i + 6] == '\n') ) { special_casing = YES; remark ("GLOB"); return (OK); } #endif #endif if (lin[*i] == GMARK || lin[*i] == XMARK) /* global markname prefix? */ { if (lin[*i] == GMARK) /* tag lines with the specified markname */ usemark = YES; else /* tag lines without the specified markname */ usemark = NO; (*i)++; *status = getkn (lin, i, &Savknm, Savknm); } if (*status == OK) /* check for a pattern prefix too */ { if (lin[*i] == GLOBAL || lin[*i] == UCGLOBAL) usepat = YES; if (lin[*i] == EXCLUDE || lin[*i] == UCEXCLUDE) usepat = NO; if (usepat != EOF) { (*i)++; if (optpat (lin, i) == ERR) *status = ERR; else (*i)++; } } if (*status == OK && usepat == EOF && usemark == EOF) *status = EOF; else if (*status == OK) defalt (1, Lastln); if (*status == OK) /* no errors so far, safe to proceed */ { remark ("GLOB"); k = Line0; /* unmark all lines preceeding range */ for (line = 0; line < Line1; line++) { k -> Globmark = NO; k = NEXTLINE(k); } for (; line <= Line2; line++) /* mark lines in range */ { if (intrpt ()) { *status = ERR; return (*status); } tmp = NO; if (usemark == EOF || usemark == YES && k -> Markname == Savknm || usemark == NO && k -> Markname != Savknm) { if (usepat == EOF) /* no global pattern to look for */ tmp = YES; else /* there is also a pattern to look for */ { gtxt (k); if (match (Txt, Pat) == usepat) tmp = YES; } } k -> Globmark = tmp; k = NEXTLINE(k); } #ifdef OLD_SCRATCH /* mark remaining lines */ for (; k != Line0; k = k -> Nextline) k -> Globmark = NO; #else /* mark remaining lines */ for (; line <= Lastln; line++) { k -> Globmark = NO; k = NEXTLINE (k); } #endif remark (""); } return (*status); } /* doglob --- do command at lin[i] on all marked lines */ int doglob (lin, i, cursav, status) char lin[]; int *i, *cursav, *status; { register int istart, line; int docmd (), getlst (), nextln (); register LINEDESC *k; LINEDESC *getind (); #ifndef OLD_SCRATCH #ifndef OLD_GLOB if (special_casing) { /* remark ("Warp 7, Captain!"); */ /* not on the screen too long anyway */ reverse (1, Lastln); Curln = Lastln; special_casing = NO; Buffer_changed = YES; First_affected = min (1, First_affected); remark (""); adjust_window (Curln, Curln); updscreen (); return (OK); } #endif #endif *status = OK; istart = *i; k = Line0; line = 0; do { line++; k = NEXTLINE(k); if (k -> Globmark == YES) /* line is marked */ { k -> Globmark = NO; /* unmark the line */ Curln = line; *cursav = Curln; /* remember where we are */ *i = istart; if (getlst (lin, i, status) == OK) docmd (lin, *i, YES, status); line = 0; /* lines may have been moved */ k = Line0; } if (intrpt ()) *status = ERR; } while (line <= Lastln && *status == OK); return (*status); } /* ckchar --- look for ch or altch on lin at i, set flag if found */ int ckchar (ch, altch, lin, i, flag, status) char ch, altch, lin[]; int *i, *flag, *status; { if (lin[*i] == ch || lin[*i] == altch) { (*i)++; *flag = YES; } else *flag = NO; *status = OK; return (OK); } /* ckp --- check for "p" after command */ int ckp (lin, i, pflag, status) char lin[]; int i, *pflag, *status; { if (lin[i] == PRINT || lin[i] == UCPRINT) { i++; *pflag = YES; } else *pflag = NO; if (lin[i] == '\n') *status = OK; else *status = ERR; return (*status); } /* ckupd --- make sure it is ok to destroy the buffer */ int ckupd (lin, i, cmd, status) char lin[], cmd; int *i, *status; { int flag; int ckchar (); *status = ckchar (ANYWAY, ANYWAY, lin, i, &flag, status); if (flag == NO && Buffer_changed == YES && Probation != cmd) { *status = ERR; Errcode = ESTUPID; Probation = cmd; /* if same command is repeated, */ } /* we'll keep quiet */ return (*status); } /* defalt --- set defaulted line numbers */ defalt (def1, def2) int def1, def2; { if (Nlines == 0) /* no line numbers supplied, use defaults */ { Line1 = def1; Line2 = def2; } return; } /* getfn --- get file name from lin[i]... */ int getfn (lin, i, file) char lin[], file[]; int i; { int j, k, ret; ret = ERR; if (lin[i + 1] == ' ') { j = i + 2; /* get new file name */ SKIPBL (lin, j); for (k = 0; lin[j] != NEWLINE; k++, j++) file[k] = lin[j]; file[k] = EOS; if (k > 0) ret = OK; } else if (lin[i + 1] == '\n' && Savfil[0] != EOS) { strcpy (file, Savfil); /* or old name */ ret = OK; } else if (lin[i + 1] == '\n') Errcode = ENOFN; else Errcode = EFILEN; if (ret == OK && Savfil[1] == EOS) { strcpy (Savfil, file); /* save if no old one */ mesg (Savfil, FILE_MSG); } return (ret); } /* getkn --- get mark name from lin[i], increment i */ int getkn (lin, i, kname, dfltnm) char lin[], *kname, dfltnm; int *i; { if (lin[*i] == '\n' || lin[*i] == EOS) { *kname = dfltnm; return (EOF); } *kname = lin[*i]; (*i)++; return (OK); } /* getrange --- get 'from' range for tlit command */ int getrange (array, k, set, size, allbut) char array[], set[]; int *k, size, *allbut; { int i, j; int addset (); Errcode = EBADLIST; /* preset error code */ i = *k + 1; if (array[i] == NOTINCCL) /* check for negated character class */ { *allbut = YES; i++; } else *allbut = NO; j = 0; filset (array[*k], array, &i, set, &j, size); if (array[i] != array[*k]) { set[0] = EOS; return (ERR); } if (set[0] == EOS) { Errcode = ENOLIST; return (ERR); } if (j > 0 && addset (EOS, set, &j, size) == NO) { set[0] = EOS; return (ERR); } *k = i; Errcode = EEGARB; return (OK); } /* getrhs --- get substitution string for 's' command */ int getrhs (lin, i, sub, gflag) char lin[], sub[]; int *i, *gflag; { static char Subs[MAXPAT] = ""; /* saved replacement pattern */ int j, maksub (); /* saved replacement pattern char */ Errcode = EBADSUB; if (lin[*i] == EOS) /* missing the middle delimeter */ return (ERR); if (lin[*i + 1] == '%' && (lin[*i + 2] == lin[*i] || lin[*i + 2] == '\n')) { /* * s//%/ --- should mean do the same thing as I did last time, even * s//&/ --- if I deleted something. So we comment out these lines. * if (Subs[0] == EOS) { Errcode = ENOSUB; return (ERR); } */ strcpy (sub, Subs); *i += 2; if (lin[*i] == '\n') { /* fix it up for pattern matching routines */ lin[*i] = lin[*i - 2]; lin[*i + 1] = '\n'; lin[*i + 2] = EOS; Peekc = SKIP_RIGHT; } } else /* not using saved substitution pattern */ { if (lin[*i + 1] == '\n') { /* missing the trailing delimiter */ /* pattern was empty */ lin[*i + 1] = lin[*i]; /* supply missing delimiter */ lin[*i + 2] = '\n'; lin[*i + 3] = EOS; Peekc = SKIP_RIGHT; /* return (ERR); /* this is the original action */ } else { /* stuff in pattern, check end of line */ for (j = *i; lin[j] != EOS; j++) ; j -= 2; /* j now points to char before '\n' */ if (lin[j] == 'p' || lin[j] == 'P') { --j; if (lin[j] == GLOBAL || lin[j] == UCGLOBAL) { if (j >= *i + 1 && lin[j-1] == lin[*i] && (lin[j-2] != ESCAPE || lin[j-3] == ESCAPE)) ; /* leave alone */ else { /* \<delim>gp\n is pattern */ /* supply trailing delim */ j += 2; /* j at \n */ lin[j] = lin[*i]; lin[++j] = '\n'; lin[++j] = EOS; Peekc = SKIP_RIGHT; } } else if (j >= *i + 1 && lin[j] == lin[*i] && (lin[j-1] != ESCAPE || lin[j-2] == ESCAPE)) ; /* leave alone */ else { /* \<delim>p\n is pattern */ /* supply trailing delim */ j += 2; lin[j] = lin[*i]; lin[++j] = '\n'; lin[++j] = EOS; Peekc = SKIP_RIGHT; } } else if (lin[j] == GLOBAL || lin[j] == UCGLOBAL) { --j; if (j >= *i + 1 && lin[j] == lin[*i] && (lin[j-1] != ESCAPE || lin[j-2] == ESCAPE)) ; /* leave alone */ else { /* \<delim>g\n is pattern */ /* supply trailing delim */ j += 2; /* j at \n */ lin[j] = lin[*i]; lin[++j] = '\n'; lin[++j] = EOS; Peekc = SKIP_RIGHT; } } else if ((lin[j] != lin[*i]) || (lin[j] == lin[*i] && lin[j-1] == ESCAPE && lin[j-2] != ESCAPE)) { /* simply missing trailing delimeter */ /* supply it */ j++; /* j at \n */ lin[j] = lin[*i]; lin[++j] = '\n'; lin[++j] = EOS; Peekc = SKIP_RIGHT; } /* else unescaped delim is there, leave well enough alone */ } if ((*i = maksub (lin, *i + 1, lin[*i], sub)) == ERR) return (ERR); strcpy (Subs, sub); /* save pattern for later */ } if (lin[*i + 1] == GLOBAL || lin[*i + 1] == UCGLOBAL) { (*i)++; *gflag = YES; } else *gflag = NO; Errcode = EEGARB; /* the default */ return (OK); } /* getstr --- get string from lin at i, copy to dst, bump i */ /* ** NOTE: this routine only called for doing the join command. ** therefore, don't do anything else with it. */ int getstr (lin, i, dst, maxdst) char lin[], dst[]; int *i, maxdst; { char delim; char esc (); int j, k, d; j = *i; Errcode = EBADSTR; delim = lin[j]; if (delim == '\n') { lin[j] = '/'; lin[++j] = ' '; /* join with a single blank */ lin[++j] = '/'; lin[++j] = '\n'; lin[++j] = EOS; j = *i; delim = lin[j]; Peekc = SKIP_RIGHT; /* now fall thru */ /* return (ERR); /* old way */ } else if ((delim == 'p' || delim == 'P') && lin[j + 1] == '\n') /* jp */ { lin[j] = '/'; lin[++j] = ' '; /* join with a single blank */ lin[++j] = '/'; lin[++j] = delim; /* 'p' or 'P' */ lin[++j] = '\n'; lin[++j] = EOS; j = *i; delim = lin[j]; Peekc = SKIP_RIGHT; /* now fall thru */ } if (lin[j + 1] == '\n') /* command was 'j/' */ { dst[0] = EOS; Errcode = ENOERR; return (OK); /* return (ERR); /* old way */ } /* * otherwise, stuff there in the string, try to allow for * a missing final delimiter. */ for (k = j + 1; lin[k] != '\n'; k++) ; /* find end */ k--; /* now points to char before newline */ if (lin[k] == 'p' || lin[k] == 'P') { k--; if (lin[k] == delim && (lin[k-1] != ESCAPE || lin[k-2] == ESCAPE)) ; /* it's fine, leave it alone */ else { /* ESCAPE delim p NEWLINE is the join string */ /* supply trailing delimiter. */ k += 2; lin[k] = delim; lin[++k] = '\n'; lin[++k] = EOS; Peekc = SKIP_RIGHT; } } else if (lin[k] != delim || (lin[k-1] == ESCAPE && lin[k-2] != ESCAPE)) { /* no delim and no p, or last char is escaped delim */ k++; lin[k] = delim; lin[++k] = '\n'; lin[++k] = EOS; Peekc = SKIP_RIGHT; } /* else delim is there leave well enough alone */ /* code to actually do the join */ for (k = j + 1; lin[k] != delim; k++) /* find end */ { if (lin[k] == '\n' || lin[k] == EOS) if (delim == ' ') break; else return (ERR); esc (lin, &k); } if (k - j > maxdst) return (ERR); for (d = 0, j++; j < k; d++, j++) dst[d] = esc (lin, &j); dst[d] = EOS; *i = j; Errcode = EEGARB; /* the default */ return (OK); } /* getwrd --- get next word from line at i; increment i */ int getwrd (line, i, word, size) char line[], word[]; int *i, size; { int j; SKIPBL (line, *i); j = 0; while (line[*i] != ' ' && line[*i] != '\n' && line[*i] != EOS) { if (j < size - 1) { word[j] = line[*i]; j++; } (*i)++; } word[j] = EOS; return (j); } /* knscan --- scan for a line with a given mark name */ int knscan (way, num) int way, *num; { int nextln (); LINEDESC *k; LINEDESC *getind (); *num = Curln; k = getind (*num); do { bump (num, &k, way); if (k -> Markname == Savknm) return (OK); } while (*num != Curln && ! intrpt ()); if (Errcode = EEGARB) Errcode = EKNOTFND; return (ERR); } /* makset --- make set from array[k] in set */ int makset (array, k, set, size) char array[], set[]; int *k, size; { static char Tset[MAXPAT] = ""; /* saved translit dest range */ int i, j; int l; int addset (); Errcode = EBADLIST; /* * try to allow missing delimiter for translit command. */ if (array[*k] == EOS) return (ERR); if (array[*k + 1] == '%' && (array[*k + 2] == array[*k] || array[*k + 2] == '\n')) { strcpy (set, Tset); *k += 2; if (array[*k] == '\n') { /* fix it up for rest of the routines */ array[*k] = array[*k - 2]; array[*k+ 1] = '\n'; array[*k+ 2] = EOS; } Peekc = SKIP_RIGHT; } else { for (l = *k; array[l] != EOS; l++) ; l -= 2; /* l now points to char before '\n' */ if (l == *k) /* "y/.../\n" */ { array[*k + 1] = array[*k]; /* add delimiter */ array[*k + 2] = '\n'; array[*k + 3] = EOS; Peekc = SKIP_RIGHT; } else if (array[l] == 'p' || array[l] == 'P') { --l; if (l >= *k + 1 && array[l] == array[*k] && (array[l-1] != ESCAPE || array[l-2] == ESCAPE)) ; /* leave alone */ else { /* \<delim>p\n is set */ /* supply trailing delim */ l += 2; array[l] = array[*k]; array[++l] = '\n'; array[++l] = EOS; Peekc = SKIP_RIGHT; } } else if (array[l] != array[*k] /* no delim, and no p */ || (array[l-1] == ESCAPE /* or last char is escaped delim */ && array[l-2] != ESCAPE)) { /* simply missing trailing delimeter */ /* supply it */ l++; /* l now at \n */ array[l] = array[*k]; array[++l] = '\n'; array[++l] = EOS; Peekc = SKIP_RIGHT; } /* else delim is there, leave well enough alone */ j = 0; i = *k + 1; filset (array[*k], array, &i, set, &j, size); if (array[i] != array[*k]) return (ERR); if (addset (EOS, set, &j, size) == NO) return (ERR); strcpy (Tset, set); /* save for later */ *k = i; } Errcode = EEGARB; return (OK); } /* optpat --- make pattern specified at lin[i] */ int optpat (lin, i) char lin[]; int *i; { int makpat (); if (lin[*i] == EOS) *i = ERR; else if (lin[*i + 1] == EOS) *i = ERR; else if (lin[*i + 1] == lin[*i]) /* repeated delimiter */ (*i)++; /* leave existing pattern alone */ else *i = makpat (lin, *i + 1, lin[*i], Pat); if (Pat [0] == EOS) { Errcode = ENOPAT; return (ERR); } if (*i == ERR) { Pat[0] = EOS; Errcode = EBADPAT; return (ERR); } return (OK); } /* ptscan --- scan for next occurrence of pattern */ int ptscan (way, num) int way, *num; { LINEDESC *getind (); LINEDESC *k; int match (); *num = Curln; k = getind (*num); do { bump (num, &k, way); gtxt (k); if (match (Txt, Pat) == YES) return (OK); } while (*num != Curln && ! intrpt ()); if (Errcode == EEGARB) Errcode = EPNOTFND; return (ERR); } /* settab --- set tab stops */ int settab (str) char str[]; { int i, j, n, maxstop, last, inc, ret; int ctoi (); for (i = 0; i < MAXLINE; i++) /* clear all tab stops */ Tabstops[i] = NO; ret = OK; maxstop = 0; last = 1; i = 0; SKIPBL (str, i); while (str[i] != EOS && str[i] != '\n') { if (str[i] == '+') /* increment */ { i++; inc = YES; } else inc = NO; n = ctoi (str, &i); if (n <= 0 || n >= MAXLINE) { ret = ERR; Errcode = ENONSENSE; break; } if (str[i] != ' ' && str[i] != '+' && str[i] != '\n' && str[i] != EOS) { ret = ERR; Errcode = EBADTABS; break; } if (inc == YES) { for (j = last + n; j < MAXLINE; j += n) { Tabstops[j - 1] = YES; maxstop = max (j, maxstop); } } else { Tabstops[n - 1] = YES; last = n; maxstop = max (n, maxstop); } SKIPBL (str, i); } /* while ... */ if (ret == ERR) maxstop = 0; if (maxstop == 0) /* no tab stops specified, use defaults */ { for (i = 4; i < MAXLINE - 1; i += 4) Tabstops[i] = YES; maxstop = i - 4 + 1; } Tabstops[0] = YES; /* always set to YES */ for (i = maxstop; i < MAXLINE; i++) Tabstops[i] = YES; return (ret); } /* serc --- read in ./.serc or $HOME/.serc and execute the commands in it. */ /* * note that se's special control characters are NOT processed, * and therefore should NOT be used in one's .serc file. */ static serc () { char file[MAXLINE]; char lin[MAXLINE]; char *expand_env (); FILE *fp; int status = ENOERR; int len, cursav; strcpy (file, expand_env ("$HOME/.serc")); if ((fp = fopen ("./.serc", "r")) == NULL || (fp = fopen (file, "r")) == NULL) return; while (fgets (lin, sizeof lin, fp) != NULL && status != EOF /*??*/) { if (lin[0] == '#' || lin[0] == '\n') continue; /* comment in .serc file */ /* most of this code stolen from edit() */ len = 0; cursav = Curln; if (getlst (lin, &len, &status) == OK) { if (ckglob (lin, &len, &status) == OK) doglob (lin, &len, &cursav, &status); else if (status != ERR) docmd (lin, len, NO, &status); } if (status == ERR) { if (Errcode == EHANGUP) hangup (); Curln = min (cursav, Lastln); } } fclose (fp); } #ifdef LOG_USAGE /* log -- log se usage */ static log () { static char logfile[] = "/usr/tmp/se.log"; /* a public file */ char logname[MAXLINE], tod[26]; /* tod => time of day */ long clock; FILE *fp; char *ctime (); long time (); int old_umask; #ifdef BSD char *getlogin (); #else char *cuserid (); #endif /* get the login name */ #ifdef BSD strcpy (logname, getlogin ()); #else cuserid (logname); #endif time (&clock); strcpy (tod, ctime (&clock)); /* see the manual on ctime(3C) */ tod[24] = EOS; /* delete the '\n' at the end */ old_umask = umask (0); /* allow writes for everyone */ /* when first call creates the file */ if ((fp = fopen (logfile, "a")) != NULL) { /* all ok, write out statistics */ fprintf (fp, "%s used se on %s.\n", logname, tod); fclose (fp); } /* else don't do anything */ umask (old_umask); } #endif /* sysname --- return a string telling us who we are */ #ifdef USG #include <sys/utsname.h> /* stuff to find out who we are */ #endif char *sysname () { int i, j, k; char c; static char buf[MAXLINE] = ""; FILE *fp; static char unknown[] = "unknown"; #ifdef USG /* System V */ static struct utsname whoarewe; uname (& whoarewe); return (whoarewe.nodename); #else #ifdef BSD4_2 /* Berkeley 4.2 */ if (buf[0] != EOS) return (buf); j = sizeof (buf); k = gethostname (buf, & j); if (k != 0) return (unknown); else return (buf); #else /* Berkeley 4.1 */ if (buf[0] != EOS) return (buf); if ((fp = fopen ("/usr/include/whoami.h", "r")) == NULL) return (unknown); else { auto char *cp; /* * file should contain a single line: * #define sysname "......" */ while ((c = getc (fp)) != '"' && c != EOF) ; if (c == EOF) cp = unknown; else { for (i = 0; (c = getc (fp)) != '"' && c != EOF; i++) buf[i] = c; buf[i] = EOS; if (c == EOF && i == 0) cp = unknown; else cp = buf; } fclose (fp); return (cp); } #endif #endif } SHAR_EOF fi # end of overwriting check echo shar: extracting "'extern.h'" '(4770 characters)' if test -f 'extern.h' then echo shar: will not over-write existing file "'extern.h'" else cat << \SHAR_EOF > 'extern.h' /* * $Header: extern.h,v 1.2 86/07/14 16:44:30 arnold Exp $ */ /* * $Log: extern.h,v $ * Revision 1.2 86/07/14 16:44:30 arnold * Removed stuff that was Georgia Tech specific. * * Revision 1.1 86/05/06 13:36:05 osadr * Initial revision * * */ /* ** extern.h ** ** external data definitions ** for the screen editor */ /* Concerning line numbers: */ extern int Line1; /* first line number on command */ extern int Line2; /* second line number on command */ extern int Nlines; /* number of line numbers specified */ extern int Curln; /* current line; value of dot */ extern int Lastln; /* last line; value of dollar */ /* Concerning patterns: */ extern char Pat[MAXPAT]; /* saved pattern */ /* Concerning the text of lines: */ extern char Txt[MAXLINE]; /* text of current line */ /* Concerning file names: */ extern char Savfil[MAXLINE]; /* remembered file name */ /* Concerning line descriptors: */ extern LINEDESC Buf[MAXBUF]; #ifdef OLD_SCRATCH extern LINEDESC *Lastbf; /* last pointer used in Buf */ extern LINEDESC *Free; /* head of free list */ #endif extern LINEDESC *Line0; /* head of list of line descriptors */ /* Concerning the 'undo' command: */ extern LINEDESC *Limbo; /* head of limbo list for undo */ extern int Limcnt; /* number of lines in limbo list */ /* Concerning the scratch file: */ extern filedes Scr; /* scratch file descriptor */ extern unsigned Scrend; /* end of info on scratch file */ extern char Scrname[MAXLINE]; /* name of scratch file */ extern int Lost_lines; /* number of garbage lines in scratch file */ /* Concerning miscellaneous variables */ extern int Buffer_changed; /* YES if buffer changed since last write */ extern int Errcode; /* cause of most recent error */ extern int Saverrcode; /* cause of previous error */ extern int Probation; /* YES if unsaved buffer can be destroyed */ extern int Argno; /* command line argument pointer */ extern char Last_char_scanned; /* last char scanned with ctl-s or -l */ #ifdef HARD_TERMS extern int Tspeed; /* terminal speed in characters/second */ #endif extern char Peekc; /* push a SKIP_RIGHT if adding delimiters */ #ifdef BSD4_2 extern int Reading; /* are we doing terminal input? */ #endif /* Concerning options: */ extern int Tabstops[MAXLINE]; /* array of tab stops */ extern char Unprintable; /* char to print for unprintable chars */ extern int Absnos; /* use absolute numbers in margin */ extern int Nchoise; /* choice of line number for cont. display */ extern int Overlay_col; /* initial cursor column for 'v' command */ extern int Warncol; /* where to turn on column warning */ extern int Firstcol; /* leftmost column to display */ extern int Indent; /* indent col; 0=same as previous line */ extern int Notify; /* notify user if he has mail in mail file */ extern int Globals; /* substitutes in a global don't fail */ extern int No_hardware; /* never use hardware insert/delete */ #ifdef HARD_TERMS /* Concerning the terminal type */ extern int Term_type; /* terminal type */ #endif /* Concerning the screen format: */ extern char Screen_image[MAXROWS][MAXCOLS]; extern char Msgalloc[MAXCOLS]; /* column allocation of status line */ extern int Nrows; /* number of rows on screen */ extern int Ncols; /* number of columns on screen */ extern int Currow; /* vertical cursor coordinate */ extern int Curcol; /* horizontal cursor coordinate */ extern int Toprow; /* top row of window field on screen */ extern int Botrow; /* bottom row of window field on screen */ extern int Cmdrow; /* row number of command line */ extern int Topln; /* line number of first line on screen */ extern int Insert_mode; /* flag to specify character insertion */ extern int Invert_case; /* flag to specify case mapping on input */ extern int First_affected; /* number of first line affected by cmd */ extern int Rel_a; /* char to use for first alpha line number */ extern int Rel_z; /* char to use for last alpha line number */ extern int Scline[MAXROWS]; /* lines currently on screen (rel to Sctop) */ extern int Sctop; /* first line currently on screen */ extern int Sclen; /* number of lines currently on screen */ extern char Blanks[MAXCOLS]; /* all blanks for filling in lines on screen */ extern char Tobuf[MAXTOBUF]; /* buffer for collecting terminal output */ extern char *Tobp; /* pointer to last used part of Tobuf */ /* Concerning interrupts: */ extern int Int_caught; /* caught a SIGINT from user */ extern int Hup_caught; /* caught a SIGHUP when phone line dropped */ #ifdef SIGTSTP extern int Catching_stops; /* catching or ignoring SIGTSTP's? */ #endif /* Concerning file encryption: */ extern int Crypting; /* doing file encryption? */ extern char Key[KEYSIZE]; /* encryption key */ SHAR_EOF fi # end of overwriting check echo shar: extracting "'m4munge'" '(704 characters)' if test -f 'm4munge' then echo shar: will not over-write existing file "'m4munge'" else cat << \SHAR_EOF > 'm4munge' #! /bin/sh # m4munge --- take what the 'where' command produces, and change it for m4 # # $Header: m4munge,v 1.2 86/07/11 15:13:56 osadr Exp $ # # $Log: m4munge,v $ # Revision 1.2 86/07/11 15:13:56 osadr # Removed Georgia Tech specific items. # # Revision 1.1 86/05/06 13:35:02 osadr # Initial revision # # # for i in $* do case $i in -DUSG) echo 'define(USG,YES)' ;; -UUSG) echo 'define(USG,NO)' ;; -DBSD) echo 'define(BSD,YES)' ;; -UBSD) echo 'define(BSD,NO)' ;; -DBSD4_2) echo 'define(BSD4_2,YES)' ;; -UBSD4_2) echo 'define(BSD4_2,NO)' ;; -DS5R2) echo 'define(S5R2,YES)' ;; -US5R2) echo 'define(S5R2,NO)' ;; -DHARD_TERMS) echo 'define(HARD_TERMS,YES)' ;; esac done SHAR_EOF chmod +x 'm4munge' fi # end of overwriting check echo shar: extracting "'main.c'" '(13208 characters)' if test -f 'main.c' then echo shar: will not over-write existing file "'main.c'" else cat << \SHAR_EOF > 'main.c' #ifndef lint static char RCSid[] = "$Header: main.c,v 1.4 86/10/07 14:50:17 arnold Exp $"; #endif /* * $Log: main.c,v $ * Revision 1.4 86/10/07 14:50:17 arnold * Changed setterm to set_term, to avoid Unix/PC shared library conflict. * * Revision 1.3 86/07/17 17:20:58 arnold * Terminal initialization code cleaned up considerably. * * Revision 1.2 86/07/11 15:12:26 osadr * Removed code that was Georgia Tech specific * * Revision 1.1 86/05/06 13:37:38 osadr * Initial revision * * */ /* ** main.c ** ** main program and lots of other routines ** for the se screen editor. */ #include "se.h" /* declare global variables */ /* Concerning line numbers: */ int Line1; /* first line number on command */ int Line2; /* second line number on command */ int Nlines; /* number of line numbers specified */ int Curln; /* current line; value of dot */ int Lastln; /* last line; value of dollar */ /* Concerning patterns: */ char Pat[MAXPAT] = ""; /* saved pattern */ /* Concerning the text of lines: */ char Txt[MAXLINE]; /* text of current line */ /* Concerning file names: */ char Savfil[MAXLINE] = ""; /* remembered file name */ /* Concerning line descriptors: */ LINEDESC Buf[MAXBUF]; LINEDESC *Line0; /* head of list of line descriptors */ #ifdef OLD_SCRATCH LINEDESC *Lastbf; /* last pointer used in Buf */ LINEDESC *Free; /* head of free list */ #endif /* Concerning the 'undo' command: */ LINEDESC *Limbo; /* head of limbo list for undo */ int Limcnt; /* number of lines in limbo list */ /* Concerning the scratch file: */ filedes Scr; /* scratch file descriptor */ unsigned Scrend; /* end of info on scratch file */ char Scrname[MAXLINE]; /* name of scratch file */ int Lost_lines; /* number of garbage lines in scratch file */ /* Concerning miscellaneous variables */ int Buffer_changed = NO;/* YES if buffer changed since last write */ int Errcode = ENOERR; /* cause of most recent error */ int Saverrcode = ENOERR;/* cause of previous error */ int Probation = NO; /* YES if unsaved buffer can be destroyed */ int Argno; /* command line argument pointer */ char Last_char_scanned = 0; /* last char scanned w/ctl-[sl], init illegal */ char Peekc = EOS; /* push a SKIP_RIGHT if adding delimiters */ #ifdef HARD_TERMS int Tspeed; /* terminal speed in characters/second */ #endif #ifdef BSD4_2 int Reading = NO; /* are we doing terminal input? */ #endif /* Concerning options: */ int Tabstops[MAXLINE]; /* array of tab stops */ char Unprintable = ' '; /* char to print for unprintable chars */ int Absnos = NO; /* use absolute numbers in margin */ int Nchoise = EOS; /* choice of line number for cont. display */ int Overlay_col = 0; /* initial cursor column for 'v' command */ int Warncol; /* where to turn on column warning, set in dosopt() */ int Firstcol = 0; /* leftmost column to display */ int Indent = 1; /* indent col; 0=same as previous line */ int Notify = YES; /* notify user if he has mail in mail file */ int Globals = NO; /* substitutes in a global don't fail */ int No_hardware; /* never use hardware insert/delete */ #ifdef HARD_TERMS /* Concerning the terminal type */ int Term_type; /* terminal type */ #endif /* Concerning the screen format: */ char Screen_image[MAXROWS][MAXCOLS]; char Msgalloc[MAXCOLS]; /* column allocation of status line */ int Nrows; /* number of rows on screen */ int Ncols; /* number of columns on screen */ int Currow; /* vertical cursor coordinate */ int Curcol; /* horizontal cursor coordinate */ int Toprow; /* top row of window field on screen */ int Botrow; /* bottom row of window field on screen */ int Cmdrow; /* row number of command line */ int Topln; /* line number of first line on screen */ int Insert_mode; /* flag to specify character insertion */ int Invert_case; /* flag to specify case mapping on input */ int First_affected; /* number of first line affected by cmd */ int Rel_a; /* char to use for first alpha line number */ int Rel_z; /* char to use for last alpha line number */ int Scline[MAXROWS]; /* lines currently on screen (rel to Sctop) */ int Sctop; /* first line currently on screen */ int Sclen; /* number of lines currently on screen */ char Blanks[MAXCOLS]; /* all blanks for filling in lines on screen */ char Tobuf[MAXTOBUF]; /* buffer for collecting terminal output */ char *Tobp = Tobuf - 1; /* pointer to last used part of Tobuf */ /* Concerning interrupts: */ int Int_caught = 0; /* caught a SIGINT from user */ int Hup_caught = 0; /* caught a SIGHUP when phone line dropped */ #ifdef BSD int Catching_stops; /* catching or ignoring SIGTSTP's? */ #endif /* Concerning file encryption: */ int Crypting = NO; /* doing file encryption? */ char Key[KEYSIZE] = ""; /* saved encryption key */ extern char *getenv (); /* main --- main program for screen editor */ main (argc, argv) int argc; char *argv[]; { char *basename (); int int_hdlr (), hup_hdlr (); int (*old_int)(), (*old_quit)(); #ifdef BSD int stop_hdlr (), (*old_stop)(); #endif /* catch quit and hangup signals */ /* * In the terminal driver munging routines, we set Control-P * to generate an interrupt, and turn off generating Quits from * the terminal. Now we just ignore them if sent from elsewhere. */ signal (SIGHUP, hup_hdlr); old_int = signal (SIGINT, int_hdlr); old_quit = signal (SIGQUIT, SIG_IGN); #ifdef notdef /* * This is commented out so that se can be run from the news * software. Commenting it out will also allow you to put it * in the background, which could give you trouble. So beware. */ if (old_int == SIG_IGN || old_quit == SIG_IGN) { /* fired off into the background, refuse to run */ if (isatty (fileno (stdin))) { fprintf (stderr, "%s: I refuse to run in the background.\n", basename (argv[0])); exit (2); } /* else assume input is a script */ } #endif #ifdef BSD old_stop = signal (SIGTSTP, stop_hdlr); if (old_stop == SIG_IGN) /* running bourne shell */ { signal (SIGTSTP, SIG_IGN); /* restore it */ Catching_stops = NO; } else Catching_stops = YES; /* running C-shell or BRL sh, catch Control-Z's */ #endif /* set terminal to no echo, no output processing, break enabled */ ttyedit (); #ifdef HARD_TERMS Tspeed = getspeed (1); /* speed of stdout */ #endif initialize (argc, argv); edit (argc, argv); #ifndef HARD_TERMS t_exit (); #endif /* reset the terminal mode */ ttynormal (); } /* error --- print error message and die semi-gracefully */ error (coredump, msg) int coredump; char *msg; { /* * You might think we want to try and save the buffer, * BUT, fatal errors can be caused by buffer problems, * which would end up putting us into a non-ending recursion. */ ttynormal (); fprintf (stderr, "%s\n", msg); signal (SIGQUIT, SIG_DFL); /* restore normal quit handling */ if (coredump) kill (getpid (), SIGQUIT); /* dump memory */ else exit (1); } /* initialize --- set up global data areas, get terminal type */ initialize (argc, argv) int argc; char *argv[]; { int i, dosopt (); Argno = 1; #ifdef HARD_TERMS /* Determine what type of terminal we're on */ if (Argno < argc && argv[Argno][0] == '-' && argv[Argno][2] == EOS && (argv[Argno][1] == 't' || argv[Argno][1] == 'T')) { Argno = 2; if (Argno < argc) { strmap (argv[Argno], 'l'); if (set_term (argv[Argno]) == ERR) usage (); else Argno++; } else usage (); } else /* fall through to the if, below */ #endif if (set_term (getenv ("TERM")) == ERR) usage (); /* Initialize the scratch file: */ mkbuf (); /* Initialize screen format parameters: */ setscreen (); /* Initialize the array of blanks to blanks */ for (i = 0; i < Ncols; i++) Blanks[i] = ' '; Blanks[i] = '\0'; if (dosopt ("") == ERR) error ("in initialize: can't happen"); } /* intrpt --- see if there has been an interrupt or hangup */ int intrpt () { if (Int_caught) { Errcode = EBREAK; Int_caught = 0; return (1); } else if (Hup_caught) { Errcode = EHANGUP; Hup_caught = 0; return (1); } return (0); } /* int_hdlr --- handle an interrupt signal */ int_hdlr () { #ifndef BSD4_2 signal (SIGINT, int_hdlr); #endif Int_caught = 1; } /* hup_hdlr --- handle a hangup signal */ hup_hdlr () { #ifndef BSD4_2 signal (SIGHUP, hup_hdlr); Hup_caught = 1; #else /* do things different cause of 4.2 (sigh) */ Hup_caught = 1; if (Reading) /* doing tty i/o, and that is where hup came from */ hangup (); #endif } #ifdef BSD /* stop_hdlr --- handle the berkeley stop/suspend signal */ int stop_hdlr () { clrscreen (); tflush (); ttynormal (); #ifdef BSD4_2 /* this handler remains in effect, use uncatchable signal */ kill (getpid(), SIGSTOP); #else /* action was reset to default when we caught it */ kill (getpid(), SIGTSTP); #endif /* * user does a "fg" */ #ifndef BSD4_2 signal (SIGTSTP, stop_hdlr); /* reset stop catching */ #endif ttyedit (); restore_screen (); } #endif /* hangup --- dump contents of edit buffer if SIGHUP occurs */ hangup () { /* close terminal to avoid hanging on any accidental I/O: */ close (0); close (1); close (2); signal (SIGHUP, SIG_IGN); signal (SIGINT, SIG_IGN); signal (SIGQUIT, SIG_IGN); Hup_caught = 0; Crypting = NO; /* force buffer to be clear text */ dowrit (1, Lastln, "se.hangup", NO, YES, NO); clrbuf (); exit (1); } /* mswait --- message waiting subroutine */ /* if the user wants to be notified, and the mail file is readable, */ /* and there is something in it, then he is given the message. */ /* the om command toggles Notify, controlling notification. */ #include <sys/types.h> #include <sys/stat.h> mswait () { int access (); struct stat buf; static char *mbox = NULL; static int first = YES; static unsigned long mtime = 0L; if (! Notify) return; if (first) { first = NO; if ((mbox = getenv ("MAIL")) != NULL && access (mbox, 4) == 0) { if (stat (mbox, &buf) >= 0) { mtime = buf.st_mtime; if (buf.st_size > 0) remark ("You have mail"); } } } else if (mbox && stat (mbox, &buf) >= 0 && buf.st_mtime > mtime) { mtime = buf.st_mtime; remark ("You have new mail"); twrite (1, "\007", 1); /* Bell */ } } /* printverboseerrormessage --- print verbose error message */ printverboseerrormessage () { switch (Errcode) { case EBACKWARD: remark ("Line numbers in backward order"); break; case ENOPAT: remark ("No saved pattern -- sorry"); break; case EBADPAT: remark ("Bad syntax in pattern"); break; case EBADSTR: remark ("Bad syntax in string parameter"); break; case EBADSUB: remark ("Bad syntax in substitution string"); break; case ECANTREAD: remark ("File is not readable"); break; case EEGARB: remark ("Garbage after your command"); break; case EFILEN: remark ("Bad syntax in file name"); break; case EBADTABS: remark ("Bad tabstop syntax"); break; case EINSIDEOUT: remark ("Can't move a group into itself"); break; case EKNOTFND: remark ("No line has that mark name"); break; case ELINE1: remark (""); break; case E2LONG: remark ("Resultant line too long to handle"); break; case ENOERR: remark ("No error to report"); break; case ENOLIMBO: remark ("No lines in limbo"); break; case EODLSSGTR: remark ("Expected '<', '>', or nothing after 'od'"); break; case EORANGE: remark ("Line number out of range"); break; case EOWHAT: remark ("Can't recognize option"); break; case EPNOTFND: remark ("No line contains that pattern"); break; case ESTUPID: remark ("Buffer hasn't been saved"); break; case EWHATZAT: remark ("No command recognized"); break; case EBREAK: remark ("You interrupted me"); break; case ELINE2: remark ("Last line number beyond end of file"); break; case ECANTWRITE: remark ("File is not writeable"); break; case ECANTINJECT: remark ("No room for any more lines!"); break; case ENOMATCH: remark ("No match for pattern"); break; case ENOFN: remark ("No saved filename"); break; case EBADLIST: remark ("Bad syntax in character list"); break; case ENOLIST: remark ("No saved character list -- sorry"); break; case ENONSENSE: remark ("Unreasonable value"); break; case ENOHELP: remark ("No help available"); break; case EBADLNR: remark ("Line numbers not allowed"); break; case EFEXISTS: remark ("File already exists"); break; case EBADCOL: remark ("Improper column number specification"); break; case ENOLANG: remark ("Unknown source language"); break; case ETRUNC: remark ("Lines were truncated"); break; case ENOSHELL: remark ("Type control-q to rebuild screen"); break; case ECANTFORK: remark ("Can't fork --- get help!"); break; case ENOSUB: remark ("No saved replacement --- sorry"); break; case ENOCMD: remark ("No saved shell command --- sorry"); break; default: remark ("?"); break; } Errcode = ENOERR; } /* usage --- print usage diagnostic and die */ usage () { ttynormal (); fprintf (stderr, "Usage: se%s%s\n", #ifdef HARD_TERMS " [ -t <terminal> ] ", #else " ", #endif "[ --acdfghiklmstuvwxyz ] [ file ... ]"); exit (1); } SHAR_EOF fi # end of overwriting check echo shar: extracting "'makefile'" '(3680 characters)' if test -f 'makefile' then echo shar: will not over-write existing file "'makefile'" else cat << \SHAR_EOF > 'makefile' # # $Header: makefile,v 1.3 86/09/19 12:16:19 arnold Exp $ # # $Log: makefile,v $ # Revision 1.3 86/09/19 12:16:19 arnold # Fixed to ignore return code from shell if statement. # # Revision 1.2 86/05/27 17:47:50 osadr # Changes to support the Unix PC (no egrep, shared library), and # to support making if . is not in the search path. # # Revision 1.1 86/05/06 13:39:18 osadr # Initial revision # # # # makefile for the Georgia Tech Screen Editor, 'se' HEADERS= ascii.h constdefs.h extern.h se.h SRCS= docmd1.c docmd2.c edit.c main.c misc.c scratch.c screen.c term.c OBJS= docmd1.o docmd2.o edit.o main.o misc.o scratch.o screen.o term.o LIBRARIES= libchangetty/libchangetty.a pat/libpat.a DOCS= makefile README MANS= scriptse.1 se.1 CFLAGS= -O `cat flags` LDFLAGS= # On BSD systems, force make to use the right shell for commands SHELL=/bin/sh ########################################################################### # Begin system dependant macro definitions # PR is to print the files nicely. Use pr -n if available, or else just pr # I use a private utility called 'prt' PR=pr # NROFF is for nroffing. we use the System V nroff. NROFF=/usr/5bin/nroff # MANSEC is where to put the manual pages. Use 'l' for local, otherwise '1'. MANSEC=l # DESTBIN is where se and scriptse will go DESTBIN= /usr/local/bin # OWNER and GROUP are the owner and group respectively OWNER= root GROUP= sys # INSTALL is the program to do the installation, use cp for real work INSTALL= cp # CHOWN changes the owner. CHOWN= /etc/chown # CHGRP changes the group. CHGRP= chgrp # CHMOD will change permissions. CHMOD= chmod ######## # other things to change: # # on non-BSD systems, change the 'lpr' below to 'lp' ######## # Begin list of dependencies all: se scriptse se.1 @echo all done se: $(OBJS) $(LIBRARIES) if grep DBSD flags > /dev/null || grep US5R2 flags > /dev/null; \ then echo -ltermlib > libs; \ else echo -lcurses > libs ; \ fi -if [ -f /lib/shlib.ifile ] ; \ then ld /lib/crt0s.o /lib/shlib.ifile $(OBJS) $(LIBRARIES) -o $@ ; \ else $(CC) $(LDFLAGS) $(OBJS) $(LIBRARIES) `cat libs` -o $@ ; \ fi rm libs $(OBJS): $(HEADERS) flags flags: where ./where > flags libchangetty/libchangetty.a: libchangetty/changetty.c cd libchangetty; make pat/libpat.a: pat/pat.c cd pat; make scriptse: scriptse.c $(CC) -O scriptse.c -o scriptse se.1: se.m4 flags (./m4munge $(CFLAGS) ; cat se.m4) | m4 | sed '/^$$/d' > se.1 install: all $(MANS) $(INSTALL) se $(DESTBIN) $(CHOWN) $(OWNER) $(DESTBIN)/se $(CHGRP) $(GROUP) $(DESTBIN)/se $(CHMOD) 711 $(DESTBIN)/se $(INSTALL) scriptse $(DESTBIN) $(CHOWN) $(OWNER) $(DESTBIN)/scriptse $(CHGRP) $(GROUP) $(DESTBIN)/scriptse $(CHMOD) 711 $(DESTBIN)/scriptse $(INSTALL) se.1 /usr/man/man$(MANSEC)/se.$(MANSEC) $(CHOWN) $(OWNER) /usr/man/man$(MANSEC)/se.$(MANSEC) $(CHGRP) $(GROUP) /usr/man/man$(MANSEC)/se.$(MANSEC) $(CHMOD) 644 /usr/man/man$(MANSEC)/se.$(MANSEC) $(INSTALL) scriptse.1 /usr/man/man$(MANSEC)/scriptse.$(MANSEC) $(CHOWN) $(OWNER) /usr/man/man$(MANSEC)/scriptse.$(MANSEC) $(CHGRP) $(GROUP) /usr/man/man$(MANSEC)/scriptse.$(MANSEC) $(CHMOD) 644 /usr/man/man$(MANSEC)/scriptse.$(MANSEC) cd se_h; make install print: $(PR) $(HEADERS) $(SRCS) $(DOCS) $(MANS) | lpr printman: $(MANS) $(NROFF) -man $(MANS) | col | lpr print2: $(HEADERS) $(SRCS) $(DOCS) $(MANS) $(PR) $? | lpr printall: printman print cd pat; make print cd libchangetty; make print cd se_h; make print clean: rm -f *.o print2 cd pat; make clean cd libchangetty; make clean clobber: clean rm -f se scriptse flags se.1 cd pat; make clobber cd libchangetty; make clobber cd se_h; make clobber SHAR_EOF fi # end of overwriting check echo shar: extracting "'misc.c'" '(3315 characters)' if test -f 'misc.c' then echo shar: will not over-write existing file "'misc.c'" else cat << \SHAR_EOF > 'misc.c' #ifndef lint static char RCSid[] = "$Header: misc.c,v 1.1 86/05/06 13:37:51 osadr Exp $"; #endif /* * $Log: misc.c,v $ * Revision 1.1 86/05/06 13:37:51 osadr * Initial revision * * */ /* ** misc.c ** ** lots of miscellanious routines for the screen editor. */ #include "se.h" #include "extern.h" /* cprow --- copy from one row to another for append */ cprow (from, to) register int from, to; { register int col; for (col = 0; col < Ncols; col++) load (Screen_image[from][col], to, col); } /* index --- return position of character in string */ int index (str, c) register char str[], c; { register int i; for (i = 0; str[i] != EOS; i++) if (str[i] == c) return (i); return (-1); } /* strbsr --- binary search stab for an entry equal to str */ int strbsr (stab, tsize, esize, str) char *stab, str[]; int tsize, esize; { /* stab should have been declared like this: static struct { char *s; ... } stab[] = { "string1", ... "string2", ... ... ... }; The call to strbsr should look like this: i = strbsr (stab, sizeof (stab), sizeof (stab[0]), str); */ register int i, j, k, x; int strcmp (); i = 0; j = tsize / esize - 1; do { k = (i + j) / 2; if ((x = strcmp (str, *(char **)(stab + esize * k))) < 0) j = k - 1; /* GREATER */ else if (x == 0) return (k); /* EQUAL */ else i = k + 1; /* LESS */ } while (i <= j); return (EOF); } /* strmap --- map a string to upper/lower case */ int strmap (str, ul) register char str[]; int ul; { register int i; if (isupper (ul)) for (i = 0; str[i] != '0'; i++) str[i] = islower (str[i]) ? toupper (str[i]) : str[i]; else for (i = 0; str[i] == EOS; i++) str[i] = isupper (str[i]) ? tolower (str[i]) : str[i]; return (i); } /* xindex --- invert condition returned by index */ int xindex (array, c, allbut, lastto) char array[], c; int allbut, lastto; { int index (); if (c == EOS) return (-1); if (allbut == NO) return (index (array, c)); if (index (array, c) > -1) return (-1); return (lastto + 1); } /* ctoi --- convert decimal string to a single precision integer */ int ctoi (str, i) register char str[]; register int *i; { register int ret; SKIPBL (str, *i); for (ret = 0; isdigit (str[*i]); (*i)++) ret = ret * 10 + (str[*i] - '0'); return (ret); } /* move_ --- move l bytes from here to there */ move_ (here, there, l) register char *here, *there; register int l; { while (l--) *there++ = *here++; } /* twrite --- stuff characters into the terminal output buffer */ twrite (fd, buf, len) register int fd, len; register char *buf; { if ((Tobp - Tobuf) + 1 + len > MAXTOBUF) tflush (); if (fd != 1 || len > MAXTOBUF) { write (fd, buf, len); return; } while (len--) *++Tobp = *buf++; } /* tflush --- clear out the terminal output buffer */ tflush () { write (1, Tobuf, (int)(Tobp - Tobuf + 1)); Tobp = Tobuf - 1; } /* basename -- return last portion of a pathname */ char *basename (str) register char *str; { register char *cp; #ifdef USG #define rindex strrchr #endif char *rindex (); if ((cp = rindex(str, '/')) == NULL) return (str); /* no '/' found, return whole name */ else return (++cp); /* skip over slash to name after it */ } SHAR_EOF fi # end of overwriting check # End of shell archive exit 0