rsalz@bbn.com (Rich Salz) (12/04/90)
Submitted-by: Wayne Davison <davison@dri.com> Posting-number: Volume 23, Issue 72 Archive-name: trn/part13 ---- Cut Here and unpack ---- #!/bin/sh # this is part 13 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file rthreads.c continued # CurArch=13 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file rthreads.c" sed 's/^X//' << 'SHAR_EOF' >> rthreads.c X printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" ); X fclose( fp_in ); X bzero( &total, sizeof (TOTAL) ); X return 0; X } X lp_bmap( &total.first, 4 ); X wp_bmap( &total.root, 5 ); X X if( !read_item( &author_cnts, (MEM_SIZE)total.author * sizeof (WORD) ) X || !read_item( &strings, (MEM_SIZE)total.string1 ) X || !read_item( &subject_cnts, (MEM_SIZE)total.subject * sizeof (WORD) ) X || !read_item( &p_roots, (MEM_SIZE)total.root * sizeof (PACKED_ROOT) ) X || !read_item( &p_articles, (MEM_SIZE)total.article * sizeof (PACKED_ARTICLE) ) ) { X printf( "\n\nRead failed for thread data -- continuing unthreaded.\n" ); X fclose( fp_in ); X unuse_data( 0 ); X return 0; X } X fclose( fp_in ); X X if( !word_same || !long_same ) { X wp_bmap( author_cnts, total.author ); X wp_bmap( subject_cnts, total.subject ); X for( i = 0; i < total.root; i++ ) { X lp_bmap( &p_roots[i].root_num, 1 ); X wp_bmap( &p_roots[i].articles, 3 ); X } X for( i = 0; i < total.article; i++ ) { X lp_bmap( &p_articles[i].num, 2 ); X wp_bmap( &p_articles[i].subject, 8 ); X } X } X X#ifndef lint X author_ptrs = (char **)safemalloc( total.author * sizeof (char **) ); X subject_ptrs = (char **)safemalloc( total.subject * sizeof (char **) ); X root_subjects = (WORD *)safemalloc( total.root * sizeof (WORD) ); X root_article_cnts = (WORD *)safemalloc( total.root * sizeof (WORD) ); X#endif X selected_roots = safemalloc( total.root * sizeof (char) ); X X bzero( root_article_cnts, total.root * sizeof (WORD) ); X bzero( selected_roots, total.root * sizeof (char) ); X X for( i = 0, ptr = strings; i < total.author; i++ ) { X author_ptrs[i] = ptr; X ptr += strlen( ptr ) + 1; X } X X for( i = 0, j = 0; i < total.root; i++ ) { X root_subjects[i] = j; X k = p_roots[i].subject_cnt; X while( k-- ) { X root_article_cnts[i] += subject_cnts[j]; X subject_ptrs[j++] = ptr; X ptr += strlen( ptr ) + 1; X } X if( saved_selections ) { X for( k = 0; k < selected_root_cnt; k++ ) { X if( p_roots[i].root_num == saved_selections[k] ) { X selected_roots[i] = 1; X } X } X } X } X count_roots( !saved_selections ); X Free( &saved_selections ); X select_page = 0; X return 1; X} X X/* A short-hand for reading a chunk of the file into a malloced array. X*/ Xstatic int Xread_item( dest, len ) Xchar **dest; XMEM_SIZE len; X{ X int ret; X X *dest = safemalloc( len ); X ret = fread( *dest, 1, (int)len, fp_in ); X if( ret != len ) { X free( *dest ); X *dest = Nullch; X return 0; X } X return 1; X} X X/* Free some memory if it hasn't already been freed. X*/ Xstatic void XFree( pp ) Xchar **pp; X{ X if( *pp ) { X free( *pp ); X *pp = Nullch; X } X} X X/* Discard the thread data that we received through the use_data() call. X** If "save_selections" is non-zero, we'll try to remember which roots X** are currently selected long enough for the use_data() call to re-use X** them. Only do this when you are going to re-open the same data file X** immediately with use_data() (presumably because the data has been X** updated while we were using it). X*/ Xvoid Xunuse_data( save_selections ) Xbool save_selections; X{ X int i, j; X X if( save_selections ) { X#ifndef lint X saved_selections X = (ART_NUM *)safemalloc( selected_root_cnt * sizeof (ART_NUM) ); X#endif X for( i = 0, j = 0; i < total.root; i++ ) { X if( selected_roots[i] && root_article_cnts[i] ) { X saved_selections[j++] = p_roots[i].root_num; X } X } X } else { X selected_root_cnt = selected_count = 0; X } X Free( &p_roots ); X Free( &root_subjects ); X Free( &author_cnts ); X Free( &subject_cnts ); X Free( &author_ptrs ); X Free( &subject_ptrs ); X Free( &root_article_cnts ); X Free( &selected_roots ); X Free( &p_articles ); X Free( &strings ); X X p_art = curr_p_art = Nullart; X init_tree(); /* free any tree lines */ X X bzero( &total, sizeof (TOTAL) ); X} X X/* Transform each WORD's byte-ordering in a buffer of the designated length. X*/ Xstatic void Xwp_bmap( buf, len ) XWORD *buf; Xint len; X{ X union { X BYTE b[sizeof (WORD)]; X WORD w; X } in, out; X register int i; X X if( word_same ) { X return; X } X while( len-- ) { X in.w = *buf; X for( i = 0; i < sizeof (WORD); i++ ) { X out.b[my_bmap.w[i]] = in.b[mt_bmap.w[i]]; X } X *buf++ = out.w; X } X} X X/* Transform each LONG's byte-ordering in a buffer of the designated length. X*/ Xstatic void Xlp_bmap( buf, len ) XLONG *buf; Xint len; X{ X union { X BYTE b[sizeof (LONG)]; X LONG l; X } in, out; X register int i; X X if( long_same ) { X return; X } X while( len-- ) { X in.l = *buf; X for( i = 0; i < sizeof (LONG); i++ ) { X out.b[my_bmap.l[i]] = in.b[mt_bmap.l[i]]; X } X *buf++ = out.l; X } X} X X#endif /* USETHREADS */ SHAR_EOF echo "File rthreads.c is complete" chmod 0660 rthreads.c || echo "restore of rthreads.c fails" echo "x - extracting rthreads.h (Text)" sed 's/^X//' << 'SHAR_EOF' > rthreads.h && X/* $Header: rthreads.h,v 4.3.3.1 90/06/20 22:56:01 davison Trn $ X** X** $Log: rthreads.h,v $ X** Revision 4.3.3.1 90/06/20 22:56:01 davison X** Initial Trn Release X** X*/ X X#include "threads.h" X XEXT TOTAL total; X XEXT PACKED_ROOT *p_roots INIT(0); XEXT WORD *root_subjects INIT(0); XEXT WORD *author_cnts INIT(0); XEXT WORD *subject_cnts INIT(0); XEXT char **author_ptrs INIT(0); XEXT char **subject_ptrs INIT(0); XEXT PACKED_ARTICLE *p_articles INIT(0); XEXT WORD *root_article_cnts INIT(0); XEXT char *selected_roots INIT(0); XEXT ART_NUM *saved_selections INIT(0); XEXT bool unread_selector INIT(0); X XEXT PACKED_ARTICLE *p_art INIT(0); XEXT PACKED_ARTICLE *curr_p_art INIT(0); XEXT PACKED_ARTICLE *recent_p_art INIT(0); X XEXT int selected_root_cnt INIT(0); XEXT ART_NUM selected_count INIT(0); XEXT int unthreaded INIT(0); XEXT int select_page; XEXT bool scan_all_roots; X XEXT bool word_same, long_same; XEXT BMAP my_bmap, mt_bmap; X Xvoid thread_init(), mybytemap(); Xchar *thread_name(), *safemalloc(); Xint use_data(); Xvoid unuse_data(); Xvoid find_article(), init_tree(), entire_tree(); Xint tree_puts(), finish_tree(); Xvoid first_art(), follow_thread(), next_root(), prev_root(); Xchar select_thread(); Xint count_roots(), count_one_root(); XPACKED_ARTICLE *upper_limit(); X X#define Nullart Null(PACKED_ARTICLE*) SHAR_EOF chmod 0660 rthreads.h || echo "restore of rthreads.h fails" echo "x - extracting search.c (Text)" sed 's/^X//' << 'SHAR_EOF' > search.c && X/* $Header: search.c,v 4.3.2.2 90/03/22 23:05:31 sob Exp $ X * X * $Log: search.c,v $ X * Revision 4.3.2.2 90/03/22 23:05:31 sob X * Fixes provided by Wayne Davison <drivax!davison> X * X * Revision 4.3.2.1 90/03/17 17:46:29 sob X * Added changes to insure that null search strings won't result in core dumps X * on non-VAX computers. X * X * Revision 4.3 85/05/01 11:50:16 lwall X * Baseline for release with 4.3bsd. X * X */ X X/* string search routines */ X X/* Copyright (c) 1981,1980 James Gosling */ X X/* Modified Aug. 12, 1981 by Tom London to include regular expressions X as in ed. RE stuff hacked over by jag to correct a few major problems, X mainly dealing with searching within the buffer rather than copying X each line to a separate array. Newlines can now appear in RE's */ X X/* Ripped to shreds and glued back together to make a search package, X * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.) X * Changes include: X * Buffer, window, and mlisp stuff gone. X * Translation tables reduced to 1 table. X * Expression buffer is now dynamically allocated. X * Character classes now implemented with a bitmap. X */ X X#include "EXTERN.h" X#include "common.h" X#include "util.h" X#include "INTERN.h" X#include "search.h" X X#ifndef BITSPERBYTE X#define BITSPERBYTE 8 X#endif X X#define BMAPSIZ (127 / BITSPERBYTE + 1) X X/* meta characters in the "compiled" form of a regular expression */ X#define CBRA 2 /* \( -- begin bracket */ X#define CCHR 4 /* a vanilla character */ X#define CDOT 6 /* . -- match anything except a newline */ X#define CCL 8 /* [...] -- character class */ X#define NCCL 10 /* [^...] -- negated character class */ X#define CDOL 12 /* $ -- matches the end of a line */ X#define CEND 14 /* The end of the pattern */ X#define CKET 16 /* \) -- close bracket */ X#define CBACK 18 /* \N -- backreference to the Nth bracketed X string */ X#define CIRC 20 /* ^ matches the beginning of a line */ X X#define WORD 32 /* matches word character \w */ X#define NWORD 34 /* matches non-word characer \W */ X#define WBOUND 36 /* matches word boundary \b */ X#define NWBOUND 38 /* matches non-(word boundary) \B */ X X#define STAR 01 /* * -- Kleene star, repeats the previous X REas many times as possible; the value X ORs with the other operator types */ X X#define ASCSIZ 0200 Xtypedef char TRANSTABLE[ASCSIZ]; X Xstatic TRANSTABLE trans = { X0000,0001,0002,0003,0004,0005,0006,0007, X0010,0011,0012,0013,0014,0015,0016,0017, X0020,0021,0022,0023,0024,0025,0026,0027, X0030,0031,0032,0033,0034,0035,0036,0037, X0040,0041,0042,0043,0044,0045,0046,0047, X0050,0051,0052,0053,0054,0055,0056,0057, X0060,0061,0062,0063,0064,0065,0066,0067, X0070,0071,0072,0073,0074,0075,0076,0077, X0100,0101,0102,0103,0104,0105,0106,0107, X0110,0111,0112,0113,0114,0115,0116,0117, X0120,0121,0122,0123,0124,0125,0126,0127, X0130,0131,0132,0133,0134,0135,0136,0137, X0140,0141,0142,0143,0144,0145,0146,0147, X0150,0151,0152,0153,0154,0155,0156,0157, X0160,0161,0162,0163,0164,0165,0166,0167, X0170,0171,0172,0173,0174,0175,0176,0177, X}; Xstatic bool folding = FALSE; X Xstatic int err; Xstatic char *FirstCharacter; X Xvoid Xsearch_init() X{ X#ifdef UNDEF X register int i; X X for (i = 0; i < ASCSIZ; i++) X trans[i] = i; X#else X ; X#endif X} X Xvoid Xinit_compex(compex) Xregister COMPEX *compex; X{ X /* the following must start off zeroed */ X X compex->eblen = 0; X compex->brastr = Nullch; X} X Xvoid Xfree_compex(compex) Xregister COMPEX *compex; X{ X if (compex->eblen) { X free(compex->expbuf); X compex->eblen = 0; X } X if (compex->brastr) { X free(compex->brastr); X compex->brastr = Nullch; X } X} X Xstatic char *gbr_str = Nullch; Xstatic int gbr_siz = 0; X Xchar * Xgetbracket(compex,n) Xregister COMPEX *compex; Xint n; X{ X int length = compex->braelist[n] - compex->braslist[n]; X X if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0) X return nullstr; X growstr(&gbr_str, &gbr_siz, length+1); X safecpy(gbr_str, compex->braslist[n], length+1); X return gbr_str; X} X Xvoid Xcase_fold(which) Xint which; X{ X register int i; X X if (which != folding) { X if (which) { X for (i = 'A'; i <= 'Z'; i++) X trans[i] = tolower(i); X } X else { X for (i = 'A'; i <= 'Z'; i++) X trans[i] = i; X } X folding = which; X } X} X X/* Compile the given regular expression into a [secret] internal format */ X Xchar * Xcompile (compex, strp, RE, fold) Xregister COMPEX *compex; Xregister char *strp; Xint RE; Xint fold; X{ X register int c; X register char *ep; X char *lastep; X char bracket[NBRA], X *bracketp; X char **alt = compex->alternatives; X char *retmes = "Badly formed search string"; X X case_fold(compex->do_folding = fold); X if (!compex->eblen) { X compex->expbuf = safemalloc(84); X compex->eblen = 80; X } X ep = compex->expbuf; /* point at expression buffer */ X *alt++ = ep; /* first alternative starts here */ X bracketp = bracket; /* first bracket goes here */ X if (*strp == 0) { /* nothing to compile? */ X if (*ep == 0) /* nothing there yet? */ X return "Null search string"; X return Nullch; /* just keep old expression */ X } X compex->nbra = 0; /* no brackets yet */ X lastep = 0; X for (;;) { X if (ep - compex->expbuf >= compex->eblen) X grow_eb(compex); X c = *strp++; /* fetch next char of pattern */ X if (c == 0) { /* end of pattern? */ X if (bracketp != bracket) { /* balanced brackets? */ X#ifdef VERBOSE X retmes = "Unbalanced parens"; X#endif X goto cerror; X } X *ep++ = CEND; /* terminate expression */ X *alt++ = 0; /* terminal alternative list */ X /* X compex->eblen = ep - compex->expbuf + 1; X compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */ X return Nullch; /* return success */ X } X if (c != '*') X lastep = ep; X if (!RE) { /* just a normal search string? */ X *ep++ = CCHR; /* everything is a normal char */ X *ep++ = c; X } X else /* it is a regular expression */ X switch (c) { X X case '\\': /* meta something */ X switch (c = *strp++) { X case '(': X if (compex->nbra >= NBRA) { X#ifdef VERBOSE X retmes = "Too many parens"; X#endif X goto cerror; X } X *bracketp++ = ++compex->nbra; X *ep++ = CBRA; X *ep++ = compex->nbra; X break; X case '|': X if (bracketp>bracket) { X#ifdef VERBOSE X retmes = "No \\| in parens"; /* Alas! */ X#endif X goto cerror; X } X *ep++ = CEND; X *alt++ = ep; X break; X case ')': X if (bracketp <= bracket) { X#ifdef VERBOSE X retmes = "Unmatched right paren"; X#endif X goto cerror; X } X *ep++ = CKET; X *ep++ = *--bracketp; X break; X case 'w': X *ep++ = WORD; X break; X case 'W': X *ep++ = NWORD; X break; X case 'b': X *ep++ = WBOUND; X break; X case 'B': X *ep++ = NWBOUND; X break; X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X *ep++ = CBACK; X *ep++ = c - '0'; X break; X default: X *ep++ = CCHR; X if (c == '\0') X goto cerror; X *ep++ = c; X break; X } X break; X case '.': X *ep++ = CDOT; X continue; X X case '*': X if (lastep == 0 || *lastep == CBRA || *lastep == CKET X || *lastep == CIRC X || (*lastep&STAR)|| *lastep>NWORD) X goto defchar; X *lastep |= STAR; X continue; X X case '^': X if (ep != compex->expbuf && ep[-1] != CEND) X goto defchar; X *ep++ = CIRC; X continue; X X case '$': X if (*strp != 0 && (*strp != '\\' || strp[1] != '|')) X goto defchar; X *ep++ = CDOL; X continue; X X case '[': { /* character class */ X register int i; X X if (ep - compex->expbuf >= compex->eblen - BMAPSIZ) X grow_eb(compex); /* reserve bitmap */ X for (i = BMAPSIZ; i; --i) X ep[i] = 0; X X if ((c = *strp++) == '^') { X c = *strp++; X *ep++ = NCCL; /* negated */ X } X else X *ep++ = CCL; /* normal */ X X i = 0; /* remember oldchar */ X do { X if (c == '\0') { X#ifdef VERBOSE X retmes = "Missing ]"; X#endif X goto cerror; X } X if (*strp == '-' && *(++strp)) X i = *strp++; X else X i = c; X while (c <= i) { X ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE); X if (fold && isalpha(c)) X ep[(c ^ 32) / BITSPERBYTE] |= X 1 << ((c ^ 32) % BITSPERBYTE); X /* set the other bit too */ X c++; X } X } while ((c = *strp++) != ']'); X ep += BMAPSIZ; X continue; X } X X defchar: X default: X *ep++ = CCHR; X *ep++ = c; X } X } Xcerror: X compex->expbuf[0] = 0; X compex->nbra = 0; X return retmes; X} X Xvoid Xgrow_eb(compex) Xregister COMPEX *compex; X{ X compex->eblen += 80; X compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4); X} X Xchar * Xexecute (compex, addr) Xregister COMPEX *compex; Xchar *addr; X{ X register char *p1 = addr; X register char *trt = trans; X register int c; X X if (addr == Nullch || compex->expbuf == Nullch) X return Nullch; X if (compex->nbra) { /* any brackets? */ X for (c = 0; c <= compex->nbra; c++) X compex->braslist[c] = compex->braelist[c] = Nullch; X if (compex->brastr) X free(compex->brastr); X compex->brastr = savestr(p1); /* in case p1 is not static */ X p1 = compex->brastr; /* ! */ X } X case_fold(compex->do_folding); /* make sure table is correct */ X FirstCharacter = p1; /* for ^ tests */ X if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) { X c = trt[compex->expbuf[1]]; /* fast check for first character */ X do { X if (trt[*p1] == c && advance (compex, p1, compex->expbuf)) X return p1; X p1++; X } while (*p1 && !err); X return Nullch; X } X else { /* regular algorithm */ X do { X register char **alt = compex->alternatives; X while (*alt) { X if (advance (compex, p1, *alt++)) X return p1; X } X p1++; X } while (*p1 && !err); X return Nullch; X } X} X X/* advance the match of the regular expression starting at ep along the X string lp, simulates an NDFSA */ Xbool Xadvance (compex, lp, ep) Xregister COMPEX *compex; Xregister char *ep; Xregister char *lp; X{ X register char *curlp; X register char *trt = trans; X register int i; X X while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET) X switch (*ep++) { X X case CCHR: X if (trt[*ep++] != trt[*lp]) return FALSE; X lp++; X continue; X X case CDOT: X if (*lp == '\n') return FALSE; X lp++; X continue; X X case CDOL: X if (!*lp || *lp == '\n') X continue; X return FALSE; X X case CIRC: X if (lp == FirstCharacter || lp[-1]=='\n') X continue; X return FALSE; X X case WORD: X if (isalnum(*lp)) { X lp++; X continue; X } X return FALSE; X X case NWORD: X if (!isalnum(*lp)) { X lp++; X continue; X } X return FALSE; X X case WBOUND: X if ((lp == FirstCharacter || !isalnum(lp[-1])) != X (!*lp || !isalnum(*lp)) ) X continue; X return FALSE; X X case NWBOUND: X if ((lp == FirstCharacter || !isalnum(lp[-1])) == X (!*lp || !isalnum(*lp))) X continue; X return FALSE; X X case CEND: X return TRUE; X X case CCL: X if (cclass (ep, *lp, 1)) { X ep += BMAPSIZ; X lp++; X continue; X } X return FALSE; X X case NCCL: X if (cclass (ep, *lp, 0)) { X ep += BMAPSIZ; X lp++; X continue; X } X return FALSE; X X case CBRA: X compex->braslist[*ep++] = lp; X continue; X X case CKET: X i = *ep++; X compex->braelist[i] = lp; X compex->braelist[0] = lp; X compex->braslist[0] = compex->braslist[i]; X continue; X X case CBACK: X if (compex->braelist[i = *ep++] == 0) { X fputs("bad braces\n",stdout) FLUSH; X err = TRUE; X return FALSE; X } X if (backref (compex, i, lp)) { X lp += compex->braelist[i] - compex->braslist[i]; X continue; X } X return FALSE; X X case CBACK | STAR: X if (compex->braelist[i = *ep++] == 0) { X fputs("bad braces\n",stdout) FLUSH; X err = TRUE; X return FALSE; X } X curlp = lp; X while (backref (compex, i, lp)) { X lp += compex->braelist[i] - compex->braslist[i]; X } X while (lp >= curlp) { X if (advance (compex, lp, ep)) X return TRUE; X lp -= compex->braelist[i] - compex->braslist[i]; X } X continue; X X case CDOT | STAR: X curlp = lp; X while (*lp++ && lp[-1] != '\n'); X goto star; X X case WORD | STAR: X curlp = lp; X while (*lp++ && isalnum(lp[-1])); X goto star; X X case NWORD | STAR: X curlp = lp; X while (*lp++ && !isalnum(lp[-1])); X goto star; X X case CCHR | STAR: X curlp = lp; X while (*lp++ && trt[lp[-1]] == trt[*ep]); X ep++; X goto star; X X case CCL | STAR: X case NCCL | STAR: X curlp = lp; X while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR))); X ep += BMAPSIZ; X goto star; X X star: X do { X lp--; X if (advance (compex, lp, ep)) X return TRUE; X } while (lp > curlp); X return FALSE; X X default: X fputs("Badly compiled pattern\n",stdout) FLUSH; X err = TRUE; X return -1; X } X if (*ep == CEND || *ep == CDOL) { X return TRUE; X } X return FALSE; X} X Xbool Xbackref (compex, i, lp) Xregister COMPEX *compex; Xregister int i; Xregister char *lp; X{ X register char *bp; X X bp = compex->braslist[i]; X while (*lp && *bp == *lp) { X bp++; X lp++; X if (bp >= compex->braelist[i]) X return TRUE; X } X return FALSE; X} X Xbool Xcclass (set, c, af) Xregister char *set; Xregister int c; X{ X c &= 0177; X#if BITSPERBYTE == 8 X if (set[c >> 3] & 1 << (c & 7)) X#else X if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE)) X#endif X return af; X return !af; X} SHAR_EOF chmod 0660 search.c || echo "restore of search.c fails" echo "x - extracting search.h (Text)" sed 's/^X//' << 'SHAR_EOF' > search.h && X/* $Header: search.h,v 4.3 85/05/01 11:50:46 lwall Exp $ X * X * $Log: search.h,v $ X * Revision 4.3 85/05/01 11:50:46 lwall X * Baseline for release with 4.3bsd. X * X */ X X#ifndef NBRA X#define NBRA 10 /* the maximum number of meta-brackets in an X RE -- \( \) */ X#define NALTS 10 /* the maximum number of \|'s */ X Xtypedef struct { X char *expbuf; /* The compiled search string */ X int eblen; /* Length of above buffer */ X char *alternatives[NALTS]; /* The list of \| seperated alternatives */ X char *braslist[NBRA]; /* RE meta-bracket start list */ X char *braelist[NBRA]; /* RE meta-bracket end list */ X char *brastr; /* saved match string after execute() */ X char nbra; /* The number of meta-brackets int the most X recenlty compiled RE */ X bool do_folding; /* fold upper and lower case? */ X} COMPEX; X Xvoid search_init(); Xvoid init_compex(); Xvoid free_compex(); Xchar *getbracket(); Xvoid case_fold(); Xchar *compile(); Xvoid grow_eb(); Xchar *execute(); Xbool advance(); Xbool backref(); Xbool cclass(); X#endif SHAR_EOF chmod 0660 search.h || echo "restore of search.h fails" echo "x - extracting sw.c (Text)" sed 's/^X//' << 'SHAR_EOF' > sw.c && X/* $Header: sw.c,v 4.3.3.1 90/06/20 22:40:11 davison Trn $ X * X * $Log: sw.c,v $ X * Revision 4.3.3.1 90/06/20 22:40:11 davison X * Initial Trn Release X * X * Revision 4.3.2.3 90/05/08 22:06:00 sob X * Added quick startup (-q) flag. X * X * Revision 4.3.2.2 90/03/22 23:05:34 sob X * Fixes provided by Wayne Davison <drivax!davison> X * X * Revision 4.3.2.1 89/12/09 00:52:40 sob X * Now handles SIGWINCH correctly. X * X * Revision 4.3.1.2 85/05/21 13:36:23 lwall X * Sped up "rn -c" by not doing unnecessary initialization. X * X * Revision 4.3.1.1 85/05/10 11:40:38 lwall X * Branch for patches. X * X * Revision 4.3 85/05/01 11:50:54 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#include "util.h" X#include "head.h" X#include "only.h" X#include "term.h" X#include "ng.h" X#include "intrp.h" X#include "INTERN.h" X#include "sw.h" X Xvoid Xsw_init(argc,argv,tcbufptr) Xint argc; Xchar *argv[]; Xchar **tcbufptr; X{ X register int i; X X if (argc >= 2 && strEQ(argv[1],"-c")) X checkflag=TRUE; /* so we can optimize for -c */ X interp(*tcbufptr,1024,GLOBINIT); X sw_file(tcbufptr,FALSE); X safecpy(*tcbufptr,getenv("RNINIT"),1024); X if (**tcbufptr) { X if (**tcbufptr == '/') { X sw_file(tcbufptr,TRUE); X } X else X sw_list(*tcbufptr); X } X X for (i = 1; i < argc; i++) X decode_switch(argv[i]); X} X Xvoid Xsw_file(tcbufptr,bleat) Xchar **tcbufptr; Xbool bleat; X{ X int initfd = open(*tcbufptr,0); X X if (initfd >= 0) { X fstat(initfd,&filestat); X if (filestat.st_size > 1024) X *tcbufptr = saferealloc(*tcbufptr,(MEM_SIZE)filestat.st_size); X if (filestat.st_size) { X read(initfd,*tcbufptr,(int)filestat.st_size); X (*tcbufptr)[filestat.st_size-1] = '\0'; X /* wipe out last newline */ X sw_list(*tcbufptr); X } X else X **tcbufptr = '\0'; X close(initfd); X } X else { X if (bleat) X printf(cantopen,*tcbufptr) FLUSH; X **tcbufptr = '\0'; X } X} X X/* decode a list of space separated switches */ X Xvoid Xsw_list(swlist) Xchar *swlist; X{ X char *tmplist = safemalloc((MEM_SIZE) strlen(swlist) + 2); X /* semi-automatic string */ X register char *p, inquote = 0; X X strcpy(tmplist,swlist); X for (p=tmplist; isspace(*p); p++) ; /* skip any initial spaces */ X while (*p) { /* "String, or nothing" */ X if (!inquote && isspace(*p)) { /* word delimiter? */ X *p++ = '\0'; /* chop here */ X while (isspace(*p)) /* these will be ignored later */ X p++; X } X else if (inquote == *p) { X strcpy(p,p+1); /* delete trailing quote */ X inquote = 0; /* no longer quoting */ X } X else if (!inquote && *p == '"' || *p == '\'') { X /* OK, I know when I am not wanted */ X inquote = *p; /* remember single or double */ X strcpy(p,p+1); /* delete the quote */ X } /* (crude, but effective) */ X else if (*p == '\\') { /* quoted something? */ X if (p[1] == '\n') /* newline? */ X strcpy(p,p+2); /* "I didn't see anything" */ X else { X strcpy(p,p+1); /* delete the backwhack */ X p++; /* leave the whatever alone */ X } X } X else X p++; /* normal char, leave it alone */ X } X *++p = '\0'; /* put an extra null on the end */ X if (inquote) X printf("Unmatched %c in switch\n",inquote) FLUSH; X for (p = tmplist; *p; /* p += strlen(p)+1 */ ) { X decode_switch(p); X while (*p++) ; /* point at null + 1 */ X } X free(tmplist); /* this oughta be in Ada */ X} X X/* decode a single switch */ X Xvoid Xdecode_switch(s) Xregister char *s; X{ X while (isspace(*s)) /* ignore leading spaces */ X s++; X#ifdef DEBUGGING X if (debug) X printf("Switch: %s\n",s) FLUSH; X#endif X if (*s != '-' && *s != '+') { /* newsgroup pattern */ X setngtodo(s); X } X else { /* normal switch */ X bool upordown = *s == '-' ? TRUE : FALSE; X char tmpbuf[LBUFLEN]; X X s++; X switch (*s) { X#ifdef TERMMOD X case '=': { X char *beg = s+1; X X while (*s && *s != '-' && *s != '+') s++; X cpytill(tmpbuf,beg,*s); X if (upordown ? strEQ(getenv("TERM"),tmpbuf) X : strNE(getenv("TERM"),tmpbuf) ) { X decode_switch(s); X } X break; X } X#endif X#ifdef BAUDMOD X case '0': case '1': case '2': case '3': case '4': X case '5': case '6': case '7': case '8': case '9': X if (upordown ? (just_a_sec*10 <= atoi(s)) X : (just_a_sec*10 >= atoi(s)) ) { X while (isdigit(*s)) s++; X decode_switch(s); X } X break; X#endif X case '/': X if (checkflag) X break; X#ifdef SETENV X setenv("SAVEDIR", upordown ? "%p/%c" : "%p" ); X setenv("SAVENAME", upordown ? "%a" : "%^C"); X#else X notincl("-/"); X#endif X break; X case 'c': X checkflag = upordown; X break; X case 'C': X s++; X if (*s == '=') s++; X docheckwhen = atoi(s); X break; X case 'd': { X if (checkflag) X break; X s++; X if (*s == '=') s++; X if (cwd) { X chdir(cwd); X free(cwd); X } X cwd = savestr(s); X break; X } X#ifdef DEBUGGING X case 'D': X s++; X if (*s == '=') s++; X if (*s) X if (upordown) X debug |= atoi(s); X else X debug &= ~atoi(s); X else X if (upordown) X debug |= 1; X else X debug = 0; X break; X#endif X case 'e': X erase_screen = upordown; X break; X case 'E': X#ifdef SETENV X s++; X if (*s == '=') X s++; X strcpy(tmpbuf,s); X s = index(tmpbuf,'='); X if (s) { X *s++ = '\0'; X setenv(tmpbuf,s); X } X else X setenv(tmpbuf,nullstr); X#else X notincl("-E"); X#endif X break; X case 'F': X s++; X indstr = savestr(s); X break; X#ifdef INNERSEARCH X case 'g': X gline = atoi(s+1)-1; X break; X#endif X case 'H': X case 'h': { X register int len, i; X char *t; X int flag = (*s == 'h' ? HT_HIDE : HT_MAGIC); X X if (checkflag) X break; X s++; X len = strlen(s); X for (t=s; *t; t++) X if (isupper(*t)) X *t = tolower(*t); X for (i=HEAD_FIRST; i<HEAD_LAST; i++) X if (!len || strnEQ(s,htype[i].ht_name,len)) X if (upordown) X htype[i].ht_flags |= flag; X else X htype[i].ht_flags &= ~flag; X break; X } X case 'i': X s++; X if (*s == '=') s++; X initlines = atoi(s); X initlines_specified = TRUE; X break; X case 'l': X muck_up_clear = upordown; X break; X case 'L': X#ifdef CLEAREOL X can_home_clear = upordown; X#else X notincl("-L"); X#endif X break; X case 'M': X mbox_always = upordown; X break; X case 'm': X s++; X if (*s == '=') s++; X if (!upordown) X marking = NOMARKING; X else if (*s == 'u') X marking = UNDERLINE; X else { X marking = STANDOUT; X } X break; X case 'N': X norm_always = upordown; X break; X#ifdef VERBOSE X case 'n': X fputs("This isn't readnews. Don't use -n.\n\n",stdout) FLUSH; X break; X#endif X case 'r': X findlast = upordown; X break; X case 's': X s++; X if (*s == '=') s++; X if (*s) { X countdown = atoi(s); X suppress_cn = FALSE; X } X else { X if (!upordown) X countdown = 5; X suppress_cn = upordown; X } X break; X case 'S': X#ifdef ARTSEARCH X s++; X if (*s == '=') s++; X if (*s) X scanon = atoi(s); X else X scanon = upordown*3; X#else X notincl("-S"); X#endif X break; X case 't': X#ifdef VERBOSE X#ifdef TERSE X verbose = !upordown; X#else X notincl("+t"); X#endif X#else X notincl("+t"); X#endif X break; X case 'T': X typeahead = upordown; X break; X case 'v': X#ifdef VERIFY X verify = upordown; X#else X notincl("-v"); X#endif X break; X case 'x': X#ifdef USETHREADS X s++; X if (*s == '=') s++; X if (*s <= '9' && *s >= '0') { X if ((max_tree_lines = atoi(s)) > 11) X max_tree_lines = 11; X do { X s++; X } while (*s <= '9' && *s >= '0'); X } else X max_tree_lines = upordown*6; X if (*s) X strncpy(select_order, s, 3); X if (mode == 'i') X use_threads = upordown; X else if (use_threads != upordown) X printf("You must exit and restart to turn threaded operation %s.\n\n", X upordown ? "on" : "off"); X#else X notincl("-x"); X#endif X break; X case 'X': X#ifdef USETHREADS X s++; X if (*s == '=') s++; X if (*s <= '9' && *s >= '0') { X select_on = atoi(s); X do { X s++; X } while (*s <= '9' && *s >= '0'); X } else X select_on = upordown; X if (*s) X end_select = *s++; X if (*s) X page_select = *s; X#else X notincl("-X"); X#endif X break; X /* X * People want a way to avoid checking for new newsgroups on startup. X */ X case 'q': X quickstart = upordown; X break; X default: X#ifdef VERBOSE X IF(verbose) X printf("\nIgnoring unrecognized switch: -%c\n", *s) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\nIgnoring -%c\n", *s) FLUSH; X#endif X break; X } X } X} X X/* print current switch values */ X Xvoid Xpr_switches() X{ X static char mp[2] = {'+','-'}; X register int i; X X fputs("\nCurrent switch settings:\n",stdout); X printf("%c/ ", mp[strEQ(getval("SAVEDIR",SAVEDIR),"%p/%c")]); X printf("%cc ", mp[checkflag]); X printf("-C%d ", docheckwhen); X printf("-d%s ", cwd); X#ifdef DEBUGGING X if (debug) X printf("-D%d ", debug); X#endif X printf("%ce ", mp[erase_screen]); X printf("-F\"%s\" ", indstr); X#ifdef INNERSEARCH X printf("-g%d", gline); X#endif X putchar('\n'); X#ifdef VERBOSE X if (verbose) { X for (i=HEAD_FIRST; i<HEAD_LAST; i++) X printf("%ch%s%c", X mp[htype[i].ht_flags & HT_HIDE], htype[i].ht_name, X (! (i % 5) ? '\n' : ' ') ); X } X#endif X printf("-i%d ", initlines); X printf("%cl ", mp[muck_up_clear]); X#ifdef CLEAREOL X printf("%cL ", mp[can_home_clear]); X#endif /* CLEAREOL */ X if (marking) X printf("-m%c ",marking==UNDERLINE?'u':'s'); X else X printf("+m "); X printf("%cM ", mp[mbox_always]); X printf("%cN ", mp[norm_always]); X printf("%cr ", mp[findlast]); X if (countdown) X printf("-s%d ", countdown); X else X printf("%cs ", mp[suppress_cn]); X#ifdef ARTSEARCH X if (scanon) X printf("-S%d ",scanon); X else X printf("+S "); X#endif X#ifdef VERBOSE X#ifdef TERSE X printf("%ct ", mp[!verbose]); X#endif X#endif X printf("%cT ", mp[typeahead]); X#ifdef VERIFY X printf("%cv ", mp[verify]); X#endif X#ifdef USETHREADS X if (use_threads) X printf("-x%d%s ",max_tree_lines,select_order); X else X printf("+x "); X if (select_on) X printf("-X%d%c%c ",select_on,end_select,page_select); X else X printf("+X "); X#endif X fputs("\n\n",stdout) FLUSH; X#ifdef ONLY X if (maxngtodo) { X#ifdef VERBOSE X IF(verbose) X fputs("Current restriction:",stdout); X ELSE X#endif X#ifdef TERSE X fputs("Only:",stdout); X#endif X for (i=0; i<maxngtodo; i++) X printf(" %s",ngtodo[i]); X fputs("\n\n",stdout) FLUSH; X } X#ifdef VERBOSE X else if (verbose) X fputs("No restriction.\n\n",stdout) FLUSH; X#endif X#endif X} X Xvoid Xcwd_check() X{ X char tmpbuf[LBUFLEN]; X X if (!cwd) X cwd = savestr(filexp("~/News")); X strcpy(tmpbuf,cwd); X if (chdir(cwd)) { X safecpy(tmpbuf,filexp(cwd),sizeof tmpbuf); X if (makedir(tmpbuf,MD_DIR) < 0 || chdir(tmpbuf) < 0) { X interp(cmd_buf, (sizeof cmd_buf), "%~/News"); X if (makedir(cmd_buf,MD_DIR) < 0) X strcpy(tmpbuf,homedir); X else X strcpy(tmpbuf,cmd_buf); X chdir(tmpbuf); X#ifdef VERBOSE X IF(verbose) X printf("\ XCannot make directory %s--\n\ X articles will be saved to %s\n\ X\n\ X",cwd,tmpbuf) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("\ XCan't make %s--\n\ X using %s\n\ X\n\ X",cwd,tmpbuf) FLUSH; X#endif X } X } X free(cwd); X getwd(tmpbuf); X if (eaccess(tmpbuf,2)) { X#ifdef VERBOSE X IF(verbose) X printf("\ XCurrent directory %s is not writeable--\n\ X articles will be saved to home directory\n\n\ X",tmpbuf) FLUSH; X ELSE X#endif X#ifdef TERSE X printf("%s not writeable--using ~\n\n",tmpbuf) FLUSH; X#endif X strcpy(tmpbuf,homedir); X } X cwd = savestr(tmpbuf); X} SHAR_EOF chmod 0660 sw.c || echo "restore of sw.c fails" echo "x - extracting sw.h (Text)" sed 's/^X//' << 'SHAR_EOF' > sw.h && X/* $Header: sw.h,v 4.3 85/05/01 11:51:07 lwall Exp $ X * X * $Log: sw.h,v $ X * Revision 4.3 85/05/01 11:51:07 lwall X * Baseline for release with 4.3bsd. X * X */ X X#ifdef INNERSEARCH XEXT int gline INIT(0); X#endif X Xvoid sw_init(); Xvoid sw_file(); Xvoid sw_list(); Xvoid decode_switch(); Xvoid pr_switches(); Xvoid cwd_check(); SHAR_EOF chmod 0660 sw.h || echo "restore of sw.h fails" echo "x - extracting term.c (Text)" sed 's/^X//' << 'SHAR_EOF' > term.c && X/* $Header: term.c,v 4.3.3.1 90/07/28 18:09:09 davison Trn $ X * X * $Log: term.c,v $ X * Revision 4.3.3.1 90/07/28 18:09:09 davison X * Initial Trn Release X * X * Revision 4.3.2.7 90/04/21 16:54:29 sob X * Installed patches provided by SCO for SCO Xenix X * X * Revision 4.3.2.6 90/04/13 23:48:17 sob X * Modifications provided by Gene Hackney for 3b2. X * X * Revision 4.3.2.5 90/04/06 20:35:08 sob X * Added fixes for SCO Xenix sent by ronald@robobar.co.uk. X * X * Revision 4.3.2.4 90/03/22 23:05:38 sob X * Fixes provided by Wayne Davison <drivax!davison> X * X * Revision 4.3.2.3 89/11/28 01:51:58 sob X * Now handles SIGWINCH correctly. X * X * Revision 4.3.2.2 89/11/27 01:31:34 sob X * Altered NNTP code per ideas suggested by Bela Lubkin X * <filbo@gorn.santa-cruz.ca.us> X * X * Revision 4.3.2.1 89/11/06 01:02:12 sob X * Added RRN support from NNTP 1.5 X * X * Revision 4.3.1.3 85/09/10 11:05:23 lwall X * Improved %m in in_char(). X * X * Revision 4.3.1.2 85/05/16 16:45:35 lwall X * Forced \r to \n on input. X * Fix for terminfo braindamage regarding bc emulation. X * X * Revision 4.3.1.1 85/05/10 11:41:03 lwall X * Branch for patches. X * X * Revision 4.3 85/05/01 11:51:10 lwall X * Baseline for release with 4.3bsd. X * X */ X X#include "EXTERN.h" X#include "common.h" X#include "util.h" X#include "final.h" X#include "help.h" X#include "cheat.h" X#include "intrp.h" X#include "INTERN.h" X#include "term.h" X X#ifdef SYS_PTEM X#include <sys/stream.h> X#include <sys/ptem.h> X#endif X Xchar ERASECH; /* rubout character */ Xchar KILLCH; /* line delete character */ Xchar tcarea[TCSIZE]; /* area for "compiled" termcap strings */ X X#ifdef USETHREADS Xint upcost; X#endif X X/* guarantee capability pointer != Nullch */ X/* (I believe terminfo will ignore the &tmpaddr argument.) */ X X#define Tgetstr(key) ((tmpstr = tgetstr(key,&tmpaddr)) ? tmpstr : nullstr) X X#ifdef PUSHBACK Xstruct keymap { X char km_type[128]; X union km_union { X struct keymap *km_km; X char *km_str; X } km_ptr[128]; X}; X X#define KM_NOTHIN 0 X#define KM_STRING 1 X#define KM_KEYMAP 2 X#define KM_BOGUS 3 X X#define KM_TMASK 3 X#define KM_GSHIFT 4 X#define KM_GMASK 7 X Xtypedef struct keymap KEYMAP; X XKEYMAP *topmap INIT(Null(KEYMAP*)); X Xvoid mac_init(); XKEYMAP *newkeymap(); Xvoid show_keymap(); Xvoid pushstring(); X#endif X Xvoid line_col_calcs(); X X/* terminal initialization */ X Xvoid Xterm_init() X{ X savetty(); /* remember current tty state */ X X#ifdef TERMIO X ospeed = _tty.c_cflag & CBAUD; /* for tputs() */ X ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */ X KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */ X#else X ospeed = _tty.sg_ospeed; /* for tputs() */ X ERASECH = _tty.sg_erase; /* for finish_command() */ X KILLCH = _tty.sg_kill; /* for finish_command() */ X#endif X X /* The following could be a table but I can't be sure that there isn't */ X /* some degree of sparsity out there in the world. */ X X switch (ospeed) { /* 1 second of padding */ X#ifdef BEXTA X case BEXTA: just_a_sec = 1920; break; X#else X#ifdef B19200 X case B19200: just_a_sec = 1920; break; X#endif X#endif X case B9600: just_a_sec = 960; break; X case B4800: just_a_sec = 480; break; X case B2400: just_a_sec = 240; break; X case B1800: just_a_sec = 180; break; X case B1200: just_a_sec = 120; break; X case B600: just_a_sec = 60; break; X case B300: just_a_sec = 30; break; X /* do I really have to type the rest of this??? */ X case B200: just_a_sec = 20; break; X case B150: just_a_sec = 15; break; X case B134: just_a_sec = 13; break; X case B110: just_a_sec = 11; break; X case B75: just_a_sec = 8; break; X case B50: just_a_sec = 5; break; X default: just_a_sec = 960; break; X /* if we are running detached I */ X } /* don't want to know about it! */ X} X X/* set terminal characteristics */ X Xvoid Xterm_set(tcbuf) Xchar *tcbuf; /* temp area for "uncompiled" termcap entry */ X{ X char *tmpaddr; /* must not be register */ X register char *tmpstr; X char *tgetstr(); X char *s; X int status; X#ifdef TIOCGWINSZ X#ifdef u3b2 Xstruct winsize { X unsigned short ws_row; /* rows, in characters*/ X unsigned short ws_col; /* columns, in character */ X unsigned short ws_xpixel; /* horizontal size, pixels */ X unsigned short ws_ypixel; /* vertical size, pixels */ X}; X#endif X struct winsize winsize; X#endif X X#ifdef PENDING X#if ! defined (FIONREAD) && ! defined (RDCHK) X /* do no delay reads on something that always gets closed on exit */ X X devtty = open("/dev/tty",0); X if (devtty < 0) { X printf(cantopen,"/dev/tty") FLUSH; X finalize(1); X } X fcntl(devtty,F_SETFL,O_NDELAY); X#endif X#endif X X /* get all that good termcap stuff */ X X#ifdef HAVETERMLIB X status = tgetent(tcbuf,getenv("TERM")); /* get termcap entry */ X if (status < 1) { X#ifdef VERBOSE X printf("No termcap %s found.\n", status ? "file" : "entry") FLUSH; X#else X fputs("Termcap botch\n",stdout) FLUSH; X#endif X finalize(1); X } X tmpaddr = tcarea; /* set up strange tgetstr pointer */ X s = Tgetstr("pc"); /* get pad character */ X PC = *s; /* get it where tputs wants it */ X if (!tgetflag("bs")) { /* is backspace not used? */ X BC = Tgetstr("bc"); /* find out what is */ X if (BC == nullstr) /* terminfo grok's 'bs' but not 'bc' */ X BC = Tgetstr("le"); X } else X BC = "\b"; /* make a backspace handy */ X UP = Tgetstr("up"); /* move up a line */ X if (!*UP) /* no UP string? */ X marking = 0; /* disable any marking */ X if (muck_up_clear) /* this is for weird HPs */ X CL = "\n\n\n\n"; X else X CL = Tgetstr("cl"); /* get clear string */ X CE = Tgetstr("ce"); /* clear to end of line string */ X#if defined(CLEAREOL) || defined(USETHREADS) X HO = Tgetstr("ho"); /* home cursor if no CM */ X CM = Tgetstr("cm"); /* cursor motion */ X if (*CM || *HO) X can_home = TRUE; X#endif X#ifdef CLEAREOL X CD = Tgetstr("cd"); /* clear to end of display */ X if (!*CE || !*CD || !can_home) /* can we CE, CD, and home? */ X can_home_clear = FALSE; /* no, so disable use of clear eol */ X#endif /* CLEAREOL */ X#ifdef USETHREADS X upcost = strlen(UP); X#endif X SO = Tgetstr("so"); /* begin standout */ X SE = Tgetstr("se"); /* end standout */ X if ((SG = tgetnum("sg"))<0) X SG = 0; /* blanks left by SG, SE */ X US = Tgetstr("us"); /* start underline */ X UE = Tgetstr("ue"); /* end underline */ X if ((UG = tgetnum("ug"))<0) X UG = 0; /* blanks left by US, UE */ X if (*US) X UC = nullstr; /* UC must not be NULL */ X else X UC = Tgetstr("uc"); /* underline a character */ X if (!*US && !*UC) { /* no underline mode? */ X US = SO; /* substitute standout mode */ X UE = SE; X UG = SG; X } X LINES = tgetnum("li"); /* lines per page */ X COLS = tgetnum("co"); /* columns on page */ X X#ifdef TIOCGWINSZ X { struct winsize ws; X if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) { X LINES = ws.ws_row; X COLS = ws.ws_col; X } X } X#endif X X AM = tgetflag("am"); /* terminal wraps automatically? */ X XN = tgetflag("xn"); /* then eats next newline? */ X VB = Tgetstr("vb"); X if (!*VB) X VB = "\007"; X CR = Tgetstr("cr"); X if (!*CR) { X if (tgetflag("nc") && *UP) { X CR = safemalloc((MEM_SIZE)strlen(UP)+2); X sprintf(CR,"%s\r",UP); X } X else X CR = "\r"; X } X#ifdef TIOCGWINSZ X if (ioctl(1, TIOCGWINSZ, &winsize)>=0) { X if (winsize.ws_row>0) LINES=winsize.ws_row; X if (winsize.ws_col>0) COLS=winsize.ws_col; X } X#endif X#else X ?????? /* Roll your own... */ X#endif X line_col_calcs(); X noecho(); /* turn off echo */ X crmode(); /* enter cbreak mode */ X X#ifdef PUSHBACK X mac_init(tcbuf); X#endif X} X X#ifdef PUSHBACK Xvoid Xmac_init(tcbuf) Xchar *tcbuf; X{ X char tmpbuf[1024]; X X tmpfp = fopen(filexp(getval("RNMACRO",RNMACRO)),"r"); X if (tmpfp != Nullfp) { X while (fgets(tcbuf,1024,tmpfp) != Nullch) { X mac_line(tcbuf,tmpbuf,(sizeof tmpbuf)); X } X fclose(tmpfp); X } X} X Xvoid Xmac_line(line,tmpbuf,tbsize) Xchar *line; Xchar *tmpbuf; Xint tbsize; X{ X register char *s, *m; X register KEYMAP *curmap; X register int ch; X register int garbage = 0; X static char override[] = "\nkeymap overrides string\n"; X X if (topmap == Null(KEYMAP*)) X topmap = newkeymap(); X if (*line == '#' || *line == '\n') X return; X if (line[ch = strlen(line)-1] == '\n') X line[ch] = '\0'; X m = dointerp(tmpbuf,tbsize,line," \t"); X if (!*m) X return; X while (*m == ' ' || *m == '\t') m++; X for (s=tmpbuf,curmap=topmap; *s; s++) { X ch = *s & 0177; X if (s[1] == '+' && isdigit(s[2])) { X s += 2; X garbage = (*s & KM_GMASK) << KM_GSHIFT; X } X else X garbage = 0; X if (s[1]) { X if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) { X fputs(override,stdout) FLUSH; X free(curmap->km_ptr[ch].km_str); X curmap->km_ptr[ch].km_str = Nullch; X } X curmap->km_type[ch] = KM_KEYMAP + garbage; X if (curmap->km_ptr[ch].km_km == Null(KEYMAP*)) X curmap->km_ptr[ch].km_km = newkeymap(); X curmap = curmap->km_ptr[ch].km_km; X } X else { X if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP) X fputs(override,stdout) FLUSH; X else { X curmap->km_type[ch] = KM_STRING + garbage; X curmap->km_ptr[ch].km_str = savestr(m); X } X } X } X} X XKEYMAP* Xnewkeymap() X{ X register int i; X register KEYMAP *map; X X#ifndef lint X map = (KEYMAP*)safemalloc(sizeof(KEYMAP)); X#else X map = Null(KEYMAP*); X#endif /* lint */ X for (i=127; i>=0; --i) { X map->km_ptr[i].km_km = Null(KEYMAP*); X map->km_type[i] = KM_NOTHIN; X } X return map; X} X Xvoid Xshow_macros() X{ X char prebuf[64]; X X if (topmap != Null(KEYMAP*)) { X print_lines("Macros:\n",STANDOUT); X *prebuf = '\0'; X show_keymap(topmap,prebuf); X } X else { X print_lines("No macros defined.\n", NOMARKING); X } X} X Xvoid Xshow_keymap(curmap,prefix) Xregister KEYMAP *curmap; Xchar *prefix; X{ X register int i; X register char *next = prefix + strlen(prefix); X register int kt; X X for (i=0; i<128; i++) { X if (kt = curmap->km_type[i]) { X if (i < ' ') X sprintf(next,"^%c",i+64); X else if (i == ' ') X strcpy(next,"\\040"); X else if (i == 127) X strcpy(next,"^?"); X else X sprintf(next,"%c",i); X if ((kt >> KM_GSHIFT) & KM_GMASK) { X sprintf(cmd_buf,"+%d", (kt >> KM_GSHIFT) & KM_GMASK); X strcat(next,cmd_buf); X } X switch (kt & KM_TMASK) { X case KM_NOTHIN: X sprintf(cmd_buf,"%s %c\n",prefix,i); X print_lines(cmd_buf,NOMARKING); X break; X case KM_KEYMAP: X show_keymap(curmap->km_ptr[(char)i].km_km, prefix); X break; X case KM_STRING: X sprintf(cmd_buf,"%s %s\n",prefix,curmap->km_ptr[i].km_str); X print_lines(cmd_buf,NOMARKING); X break; X case KM_BOGUS: X sprintf(cmd_buf,"%s BOGUS\n",prefix); X print_lines(cmd_buf,STANDOUT); X break; X } X } X } X} X X#endif X X/* routine to pass to tputs */ X Xchar Xputchr(ch) Xregister char ch; X{ X putchar(ch); X#ifdef lint X ch = Null(char); X ch = ch; X#endif X return((char) 0); X} X X/* input the 2nd and succeeding characters of a multi-character command */ X/* returns TRUE if command finished, FALSE if they rubbed out first character */ X Xbool Xfinish_command(donewline) Xint donewline; X{ X register char *s; X register bool quoteone = FALSE; X X s = buf; X if (s[1] != FINISHCMD) /* someone faking up a command? */ X return TRUE; X do { X top: X if ((unsigned char)*s < ' ') { X putchar('^'); X putchar(*s | 64); X } X else if (*s == '\177') { X putchar('^'); X putchar('?'); X } X else X putchar(*s); /* echo previous character */ X s++; Xre_read: X fflush(stdout); X getcmd(s); X if (quoteone) { X quoteone = FALSE; X continue; X } X if (errno || *s == Ctl('l')) { X *s = Ctl('r'); /* force rewrite on CONT */ X } X if (*s == '\033') { /* substitution desired? */ X#ifdef ESCSUBS X char tmpbuf[4], *cpybuf; X X tmpbuf[0] = '%'; X read_tty(&tmpbuf[1],1); X#ifdef RAWONLY X tmpbuf[1] &= 0177; X#endif X tmpbuf[2] = '\0'; X if (tmpbuf[1] == 'h') { X (void) help_subs(); X *s = '\0'; X reprint(); X goto re_read; X } X else if (tmpbuf[1] == '\033') { X *s = '\0'; X cpybuf = savestr(buf); X interp(buf, (sizeof buf), cpybuf); X free(cpybuf); X s = buf + strlen(buf); X reprint(); X goto re_read; X } X else { X interp(s,(sizeof buf) - (s-buf),tmpbuf); X fputs(s,stdout); X s += strlen(s); X } X goto re_read; X#else X notincl("^["); X *s = '\0'; X reprint(); X goto re_read; X#endif X } X else if (*s == ERASECH) { /* they want to rubout a char? */ X rubout(); X s--; /* discount the char rubbed out */ X if ((unsigned char)*s < ' ' || *s == '\177') X rubout(); X if (s == buf) { /* entire string gone? */ X fflush(stdout); /* return to single char command mode */ X return FALSE; X } X else X goto re_read; X } X else if (*s == KILLCH) { /* wipe out the whole line? */ X while (s-- != buf) { /* emulate that many ERASEs */ X rubout(); X if ((unsigned char)*s < ' ' || *s == '\177') X rubout(); X } X fflush(stdout); X return FALSE; /* return to single char mode */ X } X#ifdef WORDERASE X else if (*s == Ctl('w')) { /* wipe out one word? */ X *s-- = ' '; X while (!isspace(*s) || isspace(s[1])) { X rubout(); X if (s-- == buf) { X fflush(stdout); X return FALSE; /* return to single char mode */ X } X if ((unsigned char)*s < ' ' || *s == '\177') X rubout(); X } X s++; X goto re_read; X } X#endif X else if (*s == Ctl('r')) { X *s = '\0'; X reprint(); X goto re_read; X } X else if (*s == Ctl('v')) { X putchar('^'); X backspace(); X fflush(stdout); X getcmd(s); X goto top; X } X else if (*s == '\\') { X quoteone = TRUE; X } X } while (*s != '\n'); /* till a newline (not echoed) */ X *s = '\0'; /* terminate the string nicely */ X if (donewline) X putchar('\n') FLUSH; X return TRUE; /* say we succeeded */ X} X X/* discard any characters typed ahead */ X Xvoid Xeat_typeahead() X{ X#ifdef PUSHBACK X if (!typeahead && nextin==nextout) /* cancel only keyboard stuff */ X#else X if (!typeahead) X#endif X { X#ifdef PENDING X while (input_pending()) X read_tty(buf,sizeof(buf)); X#else /* this is probably v7 */ X ioctl(_tty_ch,TIOCSETP,&_tty); X#endif X } X} X Xvoid Xsettle_down() X{ X dingaling(); X fflush(stdout); X sleep(1); X#ifdef PUSHBACK X nextout = nextin; /* empty circlebuf */ X#endif X eat_typeahead(); X} X X#ifdef PUSHBACK X/* read a character from the terminal, with multi-character pushback */ X Xint Xread_tty(addr,size) Xchar *addr; Xint size; X{ X if (nextout != nextin) { X *addr = circlebuf[nextout++]; X nextout %= PUSHSIZE; X return 1; X } X else { X size = read(0,addr,size); X#ifdef RAWONLY X *addr &= 0177; X#endif X return size; X } X} X X#ifdef PENDING X#if ! defined (FIONREAD) && ! defined (RDCHK) Xint Xcircfill() X{ X register int Howmany = read(devtty,circlebuf+nextin,1); X X if (Howmany) { X nextin += Howmany; X nextin %= PUSHSIZE; X } X return Howmany; X} X#endif /* PENDING */ X#endif /* FIONREAD */ X Xvoid Xpushchar(c) Xchar c; X{ X nextout--; X if (nextout < 0) X nextout = PUSHSIZE - 1; X if (nextout == nextin) { X fputs("\npushback buffer overflow\n",stdout) FLUSH; X sig_catcher(0); X } X circlebuf[nextout] = c; X} X X#else /* PUSHBACK */ X#ifndef read_tty X/* read a character from the terminal, with hacks for O_NDELAY reads */ X Xint Xread_tty(addr,size) Xchar *addr; Xint size; X{ X if (is_input) { X *addr = pending_ch; X is_input = FALSE; X return 1; X } X else { X size = read(0,addr,size); X#ifdef RAWONLY X *addr &= 0177; X#endif X return size; X } X} X#endif /* read_tty */ X#endif /* PUSHBACK */ X X/* print an underlined string, one way or another */ X Xvoid Xunderprint(s) Xregister char *s; X{ X assert(UC); X if (*UC) { /* char by char underline? */ X while (*s) { X if ((unsigned char)*s < ' ') { X putchar('^'); X backspace();/* back up over it */ X underchar();/* and do the underline */ X putchar(*s+64); X backspace();/* back up over it */ X underchar();/* and do the underline */ X } X else { X putchar(*s); X backspace();/* back up over it */ X underchar();/* and do the underline */ X } X s++; X } X } X else { /* start and stop underline */ X underline(); /* start underlining */ X while (*s) { X if ((unsigned char)*s < ' ') { X putchar('^'); X putchar(*s+64); X } X else X putchar(*s); X s++; X } X un_underline(); /* stop underlining */ X } X} X X/* keep screen from flashing strangely on magic cookie terminals */ X X#ifdef NOFIREWORKS Xvoid Xno_sofire() X{ X if (*UP && *SE) { /* should we disable fireworks? */ X putchar('\n'); X un_standout(); X up_line(); X carriage_return(); X } X} X Xvoid Xno_ulfire() X{ X if (*UP && *US) { /* should we disable fireworks? */ X putchar('\n'); X un_underline(); X up_line(); X carriage_return(); X } X} X#endif X X/* get a character into a buffer */ X Xvoid Xgetcmd(whatbuf) Xregister char *whatbuf; X{ X#ifdef PUSHBACK X register KEYMAP *curmap; X register int i; X bool no_macros; X int times = 0; /* loop detector */ X char scrchar; X Xtryagain: X curmap = topmap; X no_macros = (whatbuf != buf && nextin == nextout); X#endif X for (;;) { X int_count = 0; X errno = 0; X if (read_tty(whatbuf,1) < 0) X if (!errno) X errno = EINTR; X else { X perror(readerr); X sig_catcher(0); X } X#ifdef PUSHBACK X if (*whatbuf & 0200 || no_macros) { X *whatbuf &= 0177; X goto got_canonical; X } X if (curmap == Null(KEYMAP*)) X goto got_canonical; X for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){ X read_tty(&scrchar,1); X } X switch (curmap->km_type[*whatbuf] & KM_TMASK) { X case KM_NOTHIN: /* no entry? */ X if (curmap == topmap) /* unmapped canonical */ X goto got_canonical; X settle_down(); X goto tryagain; X case KM_KEYMAP: /* another keymap? */ X curmap = curmap->km_ptr[*whatbuf].km_km; X assert(curmap != Null(KEYMAP*)); X break; X case KM_STRING: /* a string? */ X pushstring(curmap->km_ptr[*whatbuf].km_str); X if (++times > 20) { /* loop? */ X fputs("\nmacro loop?\n",stdout); X settle_down(); X } X no_macros = FALSE; X goto tryagain; X } X#else X#ifdef RAWONLY X *whatbuf &= 0177; X#endif X break; X#endif X } X Xgot_canonical: X#ifndef TERMIO X if (*whatbuf == '\r') X *whatbuf = '\n'; X#endif X if (whatbuf == buf) X whatbuf[1] = FINISHCMD; /* tell finish_command to work */ X} X X#ifdef PUSHBACK Xvoid Xpushstring(str) Xchar *str; X{ X register int i; X char tmpbuf[PUSHSIZE]; X register char *s = tmpbuf; X X assert(str != Nullch); X interp(s,PUSHSIZE,str); X for (i = strlen(s)-1; i >= 0; --i) { X s[i] ^= 0200; X pushchar(s[i]); X } X} X#endif X Xint Xget_anything() X{ X char tmpbuf[2]; X Xreask_anything: X unflush_output(); /* disable any ^O in effect */ X standout(); X#ifdef VERBOSE X IF(verbose) X fputs("[Type space to continue] ",stdout); X ELSE X#endif X#ifdef TERSE X fputs("[MORE] ",stdout); X#endif X un_standout(); X fflush(stdout); X eat_typeahead(); X if (int_count) { X return -1; X } X collect_subjects(); /* loads subject cache until */ X /* input is pending */ X getcmd(tmpbuf); X if (errno || *tmpbuf == '\f') { X putchar('\n') FLUSH; /* if return from stop signal */ X goto reask_anything; /* give them a prompt again */ X } X if (*tmpbuf == 'h') { X#ifdef VERBOSE X IF(verbose) X fputs("\nType q to quit or space to continue.\n",stdout) FLUSH; X ELSE X#endif X#ifdef TERSE X fputs("\nq to quit, space to continue.\n",stdout) FLUSH; X#endif X goto reask_anything; X } X else if (*tmpbuf != ' ' && *tmpbuf != '\n') { X carriage_return(); X erase_eol(); /* erase the prompt */ X carriage_return(); X return *tmpbuf == 'q' ? -1 : *tmpbuf; X } X if (*tmpbuf == '\n') { X page_line = LINES - 1; X carriage_return(); X erase_eol(); X carriage_return(); X } X else { X page_line = 1; X if (erase_screen) /* -e? */ X clear(); /* clear screen */ X else { X carriage_return(); X erase_eol(); /* erase the prompt */ X carriage_return(); X } X } X return 0; X} X X#ifdef USETHREADS Xint Xpause_getcmd() X{ X unflush_output(); /* disable any ^O in effect */ X standout(); X#ifdef VERBOSE X IF(verbose) X fputs("[Type space or a command] ",stdout); X ELSE X#endif X#ifdef TERSE X fputs("[CMD] ",stdout); X#endif X un_standout(); X fflush(stdout); X eat_typeahead(); X if (int_count) { X return -1; X } X getcmd(buf); X if (errno || *buf == '\f') { X return 0; /* if return from stop signal */ X } X else if (*buf != ' ') { X carriage_return(); X erase_eol(); /* erase the prompt */ X carriage_return(); X return *buf; X } X return 0; X} X#endif X Xvoid Xin_char(prompt, newmode) Xchar *prompt; Xchar newmode; X{ X char oldmode = mode; X Xreask_in_char: X unflush_output(); /* disable any ^O in effect */ X fputs(prompt,stdout); X fflush(stdout); X eat_typeahead(); X mode = newmode; X getcmd(buf); X if (errno || *buf == '\f') { X putchar('\n') FLUSH; /* if return from stop signal */ X goto reask_in_char; /* give them a prompt again */ X } X mode = oldmode; X} X Xint Xprint_lines(what_to_print,hilite) Xchar *what_to_print; Xint hilite; X{ X register char *s; X register int i; X X if (page_line < 0) /* they do not want to see this? */ X return -1; X for (s=what_to_print; *s; ) { X if (page_line >= LINES || int_count) { X if (i = -1, int_count || (i = get_anything())) { X page_line = -1; /* disable further print_lines */ X return i; X } X } X page_line++; X if (hilite == STANDOUT) { X#ifdef NOFIREWORKS X if (erase_screen) X no_sofire(); X#endif X standout(); X } X else if (hilite == UNDERLINE) { X#ifdef NOFIREWORKS X if (erase_screen) X no_ulfire(); X#endif X underline(); X } X for (i=0; i<COLS; i++) { X if (!*s) X break; X if ((unsigned char)*s >= ' ') X putchar(*s); X else if (*s == '\t') { X putchar(*s); X i = ((i+8) & ~7) - 1; X } X else if (*s == '\n') { X i = 32000; X } X else { X i++; X putchar('^'); X putchar(*s + 64); X } X s++; X } X if (i) { X if (hilite == STANDOUT) X un_standout(); X else if (hilite == UNDERLINE) X un_underline(); X if (AM && i == COLS) X fflush(stdout); X else X putchar('\n') FLUSH; X } X } X return 0; X} X Xvoid Xpage_init() X{ X page_line = 1; X if (erase_screen) X clear(); X else X putchar('\n') FLUSH; X} X Xvoid Xpad(num) Xint num; X{ X register int i; X X for (i = num; i; --i) X putchar(PC); X fflush(stdout); X} X X/* echo the command just typed */ X X#ifdef VERIFY Xvoid Xprintcmd() X{ X if (verify && buf[1] == FINISHCMD) { X if ((unsigned char)*buf < ' ') { X putchar('^'); X putchar(*buf | 64); X backspace(); X backspace(); X } X else { X putchar(*buf); X backspace(); X } X fflush(stdout); X } X} X#endif X Xvoid Xrubout() X{ X backspace(); /* do the old backspace, */ X putchar(' '); /* space, */ X backspace(); /* backspace trick */ X} X Xvoid Xreprint() X{ X register char *s; X X fputs("^R\n",stdout) FLUSH; X for (s = buf; *s; s++) { X if ((unsigned char)*s < ' ') { SHAR_EOF echo "End of part 13" echo "File term.c is continued in part 14" echo "14" > s2_seq_.tmp exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.