Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/3/84; site genrad.UUCP Path: utzoo!decvax!genrad!sources-request From: sources-request@genrad.UUCP Newsgroups: mod.sources Subject: rn version 4.3 (kit 4 of 9) Message-ID: <825@genrad.UUCP> Date: Fri, 10-May-85 17:00:09 EDT Article-I.D.: genrad.825 Posted: Fri May 10 17:00:09 1985 Date-Received: Sun, 12-May-85 02:52:11 EDT Sender: john@genrad.UUCP Organization: System Development Corporation R&D, Santa Monica Lines: 2803 Approved: john@genrad.UUCP From: lwall@sdcrdcf.UUCP (Larry Wall) ---------------- cut here --------------- #! /bin/sh # Make a new directory for the rn sources, cd to it, and run kits 1 thru 9 # through sh. When all 9 kits have been run, read README. echo "This is rn kit 4 (of 9). If kit 4 is complete, the line" echo '"'"End of kit 4 (of 9)"'" will echo at the end.' echo "" export PATH || (echo "You didn't use sh, you clunch." ; kill $$) echo Extracting ng.c cat >ng.c <<'!STUFFY!FUNK!' /* $Header: ng.c,v 4.3 85/05/01 11:43:43 lwall Exp $ * * $Log: ng.c,v $ * Revision 4.3 85/05/01 11:43:43 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "rn.h" #include "term.h" #include "final.h" #include "util.h" #include "artsrch.h" #include "cheat.h" #include "help.h" #include "kfile.h" #include "rcstuff.h" #include "head.h" #include "artstate.h" #include "bits.h" #include "art.h" #include "artio.h" #include "ngstuff.h" #include "intrp.h" #include "respond.h" #include "ngdata.h" #include "backpage.h" #include "rcln.h" #include "last.h" #include "INTERN.h" #include "ng.h" #include "artstate.h" /* somebody has to do it */ /* art_switch() return values */ #define AS_NORM 0 #define AS_INP 1 #define AS_ASK 2 #define AS_CLEAN 3 ART_NUM recent_art = 0; /* previous article # for '-' command */ ART_NUM curr_art = 0; /* current article # */ int exit_code = NG_NORM; void ng_init() { #ifdef KILLFILES open_kfile(KF_GLOBAL); #endif } /* do newsgroup on line ng with name ngname */ /* assumes that we are chdir'ed to SPOOL, and assures that that is * still true upon return, but chdirs to SPOOL/ngname in between * * If you can understand this routine, you understand most of the program. * The basic structure is: * for each desired article * for each desired page * for each line on page * if we need another line from file * get it * if it's a header line * do special things * for each column on page * put out a character * end loop * end loop * end loop * end loop * * (Actually, the pager is in another routine.) * * The chief problem is deciding what is meant by "desired". Most of * the messiness of this routine is due to the fact that people want * to do unstructured things all the time. I have used a few judicious * goto's where I thought it improved readability. The rest of the messiness * arises from trying to be both space and time efficient. Have fun. */ int do_newsgroup(start_command) char *start_command; /* command to fake up first */ { char oldmode = mode; register long i; /* scratch */ int skipstate; /* how many unavailable articles */ /* have we skipped already? */ char *whatnext = "%sWhat next? [%s]"; #ifdef ARTSEARCH srchahead = (scanon && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0); /* did they say -S? */ #endif mode = 'a'; recent_art = curr_art = 0; exit_code = NG_NORM; if (eaccess(ngdir,5)) { /* directory read protected? */ if (eaccess(ngdir,0)) { #ifdef VERBOSE IF(verbose) printf("\nNewsgroup %s does not have a spool directory!\n", ngname) FLUSH; ELSE #endif #ifdef TERSE printf("\nNo spool for %s!\n",ngname) FLUSH; #endif #ifdef CATCHUP catch_up(ng); #endif toread[ng] = TR_NONE; } else { #ifdef VERBOSE IF(verbose) printf("\nNewsgroup %s is not currently accessible.\n", ngname) FLUSH; ELSE #endif #ifdef TERSE printf("\n%s not readable.\n",ngname) FLUSH; #endif toread[ng] = TR_NONE; /* make this newsgroup invisible */ /* (temporarily) */ } mode = oldmode; return -1; } /* chdir to newsgroup subdirectory */ if (chdir(ngdir)) { printf(nocd,ngdir) FLUSH; mode = oldmode; return -1; } #ifdef CACHESUBJ subj_list = Null(char **); /* no subject list till needed */ #endif /* initialize control bitmap */ if (initctl()) { mode = oldmode; return -1; } /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */ in_ng = TRUE; /* tell the world we are here */ forcelast = TRUE; /* if 0 unread, do not bomb out */ art=firstart; /* remember what newsgroup we were in for sake of posterity */ writelast(); /* do they want a special top line? */ firstline = getval("FIRSTLINE",Nullch); /* see if there are any special searches to do */ #ifdef KILLFILES open_kfile(KF_LOCAL); #ifdef VERBOSE IF(verbose) kill_unwanted(firstart,"Looking for articles to kill...\n\n",TRUE); ELSE #endif #ifdef TERSE kill_unwanted(firstart,"Killing...\n\n",TRUE); #endif #endif /* now read each unread article */ rc_changed = doing_ng = TRUE; /* enter the twilight zone */ skipstate = 0; /* we have not skipped anything (yet) */ checkcount = 0; /* do not checkpoint for a while */ do_fseek = FALSE; /* start 1st article at top */ if (art > lastart) art=firstart; /* init the for loop below */ for (; art<=lastart+1; ) { /* for each article */ /* do we need to "grow" the newsgroup? */ if (art > lastart || forcegrow) grow_ctl(); check_first(art); /* make sure firstart is still 1st */ if (start_command) { /* fake up an initial command? */ prompt = whatnext; strcpy(buf,start_command); free(start_command); start_command = Nullch; art = lastart+1; goto article_level; } if (art>lastart) { /* are we off the end still? */ ART_NUM ucount = 0; /* count of unread articles left */ for (i=firstart; i<=lastart; i++) if (!(ctl_read(i))) ucount++; /* count the unread articles */ #ifdef DEBUGGING /*NOSTRICT*/ if (debug && ((ART_NUM)toread[ng]) != ucount) printf("(toread=%ld sb %ld)",(long)toread[ng],(long)ucount) FLUSH; #endif /*NOSTRICT*/ toread[ng] = (ART_UNREAD)ucount; /* this is perhaps pointless */ art = lastart + 1; /* keep bitmap references sane */ if (art != curr_art) { recent_art = curr_art; /* remember last article # (for '-') */ curr_art = art; /* remember this article # */ } if (erase_screen) clear(); /* clear the screen */ else fputs("\n\n",stdout) FLUSH; #ifdef VERBOSE IF(verbose) printf("End of newsgroup %s.",ngname); /* print pseudo-article */ ELSE #endif #ifdef TERSE printf("End of %s",ngname); #endif if (ucount) { printf(" (%ld article%s still unread)", (long)ucount,ucount==1?nullstr:"s"); } else { if (!forcelast) goto cleanup; /* actually exit newsgroup */ } prompt = whatnext; #ifdef ARTSEARCH srchahead = 0; /* no more subject search mode */ #endif fputs("\n\n",stdout) FLUSH; skipstate = 0; /* back to none skipped */ } else if (!reread && was_read(art)) { /* has this article been read? */ art++; /* then skip it */ continue; } else if (!reread && !was_read(art) && artopen(art) == Nullfp) { /* never read it, & cannot find it? */ if (errno != ENOENT) { /* has it not been deleted? */ #ifdef VERBOSE IF(verbose) printf("\n(Article %ld exists but is unreadable.)\n", (long)art) FLUSH; ELSE #endif #ifdef TERSE printf("\n(%ld unreadable.)\n",(long)art) FLUSH; #endif skipstate = 0; sleep(2); } switch(skipstate++) { case 0: clear(); #ifdef VERBOSE IF(verbose) fputs("Skipping unavailable article",stdout); ELSE #endif #ifdef TERSE fputs("Skipping",stdout); #endif for (i = just_a_sec/3; i; --i) putchar(PC); fflush(stdout); sleep(1); break; case 1: fputs("..",stdout); fflush(stdout); break; default: putchar('.'); fflush(stdout); #define READDIR #ifdef READDIR { /* fast skip patch */ ART_NUM newart; if (! (newart=getngmin(".",art))) newart = lastart+1; for (i=art; i=0; --i) if (subj_list[i]) free(subj_list[i]); #ifndef lint free((char*)subj_list); #endif lint } #endif write_rc(); /* and update .newsrc */ rc_changed = FALSE; /* tell sig_catcher it is ok */ if (chdir(spool)) { printf(nocd,spool) FLUSH; sig_catcher(0); } #ifdef KILLFILES if (localkfp) { fclose(localkfp); localkfp = Nullfp; } #endif mode = oldmode; return exit_code; } /* Whew! */ /* decide what to do at the end of an article */ int art_switch() { register ART_NUM i; setdef(buf,dfltcmd); #ifdef VERIFY printcmd(); #endif switch (*buf) { case 'p': /* find previous unread article */ do { if (art <= firstart) break; art--; } while (was_read(art) || artopen(art) == Nullfp); #ifdef ARTSEARCH srchahead = 0; #endif return AS_NORM; case 'P': /* goto previous article */ if (art > absfirst) art--; else { #ifdef VERBOSE IF(verbose) fputs("\n\ There are no articles prior to this one.\n\ ",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs("\nNo previous articles\n",stdout) FLUSH; #endif return AS_ASK; } reread = TRUE; #ifdef ARTSEARCH srchahead = 0; #endif return AS_NORM; case '-': if (recent_art) { art = recent_art; reread = TRUE; #ifdef ARTSEARCH srchahead = -(srchahead != 0); #endif return AS_NORM; } else { exit_code = NG_MINUS; return AS_CLEAN; } case 'n': /* find next unread article? */ if (art > lastart) { if (toread[ng]) art = firstart; else return AS_CLEAN; } #ifdef ARTSEARCH else if (scanon && srchahead) { *buf = Ctl('n'); goto normal_search; } #endif else art++; #ifdef ARTSEARCH srchahead = 0; #endif return AS_NORM; case 'N': /* goto next article */ if (art > lastart) art = absfirst; else art++; if (art <= lastart) reread = TRUE; #ifdef ARTSEARCH srchahead = 0; #endif return AS_NORM; case '$': art = lastart+1; forcelast = TRUE; #ifdef ARTSEARCH srchahead = 0; #endif return AS_NORM; case '1': case '2': case '3': /* goto specified article */ case '4': case '5': case '6': /* or do something with a range */ case '7': case '8': case '9': case '.': forcelast = TRUE; switch (numnum()) { case NN_INP: return AS_INP; case NN_ASK: return AS_ASK; case NN_REREAD: reread = TRUE; #ifdef ARTSEARCH if (srchahead) srchahead = -1; #endif break; case NN_NORM: if (was_read(art)) { art = firstart; pad(just_a_sec/3); } else return AS_ASK; break; } return AS_NORM; case Ctl('k'): edit_kfile(); return AS_ASK; case 'K': case 'k': case Ctl('n'): case Ctl('p'): case '/': case '?': #ifdef ARTSEARCH normal_search: { /* search for article by pattern */ char cmd = *buf; reread = TRUE; /* assume this */ switch (art_search(buf, (sizeof buf), TRUE)) { case SRCH_ERROR: return AS_ASK; case SRCH_ABORT: return AS_INP; case SRCH_INTR: #ifdef VERBOSE IF(verbose) printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH; ELSE #endif #ifdef TERSE printf("\n(Intr at %ld)\n",(long)art) FLUSH; #endif art = curr_art; /* restore to current article */ return AS_ASK; case SRCH_DONE: fputs("done\n",stdout) FLUSH; pad(just_a_sec/3); /* 1/3 second */ if (srchahead) art = firstart; else art = curr_art; reread = FALSE; return AS_NORM; case SRCH_SUBJDONE: #ifdef UNDEF fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH; pad(just_a_sec/3); /* 1/3 second */ #endif art = firstart; reread = FALSE; return AS_NORM; case SRCH_NOTFOUND: fputs("\n\n\n\nNot found.\n",stdout) FLUSH; art = curr_art; /* restore to current article */ return AS_ASK; case SRCH_FOUND: if (cmd == Ctl('n') || cmd == Ctl('p')) oldsubject = TRUE; break; } return AS_NORM; } #else buf[1] = '\0'; notincl(buf); return AS_ASK; #endif case 'u': /* unsubscribe from this newsgroup? */ rcchar[ng] = NEGCHAR; return AS_CLEAN; case 'M': #ifdef DELAYMARK if (art <= lastart) { delay_unmark(art); printf("\nArticle %ld will return.\n",(long)art) FLUSH; } #else notincl("M"); #endif return AS_ASK; case 'm': if (art <= lastart) { unmark_as_read(art); printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH; } return AS_ASK; case 'c': /* catch up */ reask_catchup: #ifdef VERBOSE IF(verbose) in_char("\nDo you really want to mark everything as read? [yn] "); ELSE #endif #ifdef TERSE in_char("\nReally? [ynh] "); #endif putchar('\n') FLUSH; setdef(buf,"y"); #ifdef VERIFY printcmd(); #endif if (*buf == 'h') { #ifdef VERBOSE IF(verbose) fputs("\ Type y or SP to mark all articles as read.\n\ Type n to leave articles marked as they are.\n\ Type u to mark everything read and unsubsubscribe.\n\ ",stdout) FLUSH; ELSE #endif #ifdef TERSE fputs("\ y or SP to mark all read.\n\ n to forget it.\n\ u to mark all and unsubscribe.\n\ ",stdout) FLUSH; #endif goto reask_catchup; } else if (*buf == 'n' || *buf == 'q') { return AS_ASK; } else if (*buf != 'y' && *buf != 'u') { fputs(hforhelp,stdout) FLUSH; settle_down(); goto reask_catchup; } for (i = firstart; i <= lastart; i++) { ctl_set(i); /* mark as read */ } #ifdef DELAYMARK if (dmfp) yankback(); #endif if (*buf == 'u') { rcchar[ng] = NEGCHAR; return AS_CLEAN; } art = lastart+1; forcelast = FALSE; return AS_NORM; case 'Q': exit_code = NG_ASK; /* FALL THROUGH */ case 'q': /* go back up to newsgroup level? */ return AS_CLEAN; case 'j': putchar('\n') FLUSH; if (art <= lastart) mark_as_read(art); return AS_ASK; case 'h': { /* help? */ int cmd; if ((cmd = help_art()) > 0) pushchar(cmd); return AS_ASK; } case '&': if (switcheroo()) /* get rest of command */ return AS_INP; /* if rubbed out, try something else */ return AS_ASK; case '#': #ifdef VERBOSE IF(verbose) printf("\nThe last article is %ld.\n",(long)lastart) FLUSH; ELSE #endif #ifdef TERSE printf("\n%ld\n",(long)lastart) FLUSH; #endif return AS_ASK; case '=': { char tmpbuf[256]; ART_NUM oldart = art; int cmd; char *subjline = getval("SUBJLINE",Nullch); #ifndef CACHESUBJ char *s; #endif page_init(); #ifdef CACHESUBJ if (!subj_list) fetchsubj(art,TRUE,FALSE); #endif for (i=firstart; i<=lastart && !int_count; i++) { #ifdef CACHESUBJ if (!was_read(i) && (subj_list[OFFSET(i)] != Nullch || fetchsubj(i,FALSE,FALSE)) && *subj_list[OFFSET(i)] ) { sprintf(tmpbuf,"%5ld ", i); if (subjline) { art = i; interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline); } else safecpy(tmpbuf + 6, subj_list[OFFSET(i)], (sizeof tmpbuf) - 6); if (cmd = print_lines(tmpbuf,NOMARKING)) { if (cmd > 0) pushchar(cmd); break; } } #else if (!was_read(i) && (s = fetchsubj(i,FALSE,FALSE)) && *s) { sprintf(tmpbuf,"%5ld ", i); if (subjline) { /* probably fetches it again! */ art = i; interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline); } else safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6); if (cmd = print_lines(tmpbuf,NOMARKING)) { if (cmd > 0) pushchar(cmd); break; } } #endif } int_count = 0; art = oldart; return AS_ASK; } case '^': art = firstart; #ifdef ARTSEARCH srchahead = 0; #endif return AS_NORM; #if defined(CACHESUBJ) && defined(DEBUGGING) case 'D': printf("\nFirst article: %ld\n",(long)firstart) FLUSH; if (!subj_list) fetchsubj(art,TRUE,FALSE); if (subj_list != Null(char **)) { for (i=1; i<=lastart && !int_count; i++) { if (subj_list[OFFSET(i)]) printf("%5ld %c %s\n", i, (was_read(i)?'y':'n'), subj_list[OFFSET(i)]) FLUSH; } } int_count = 0; return AS_ASK; #endif case 'v': if (art <= lastart) { reread = TRUE; do_hiding = FALSE; } return AS_NORM; #ifdef ROTATION case Ctl('x'): #endif case Ctl('r'): #ifdef ROTATION rotate = (*buf==Ctl('x')); #endif if (art <= lastart) reread = TRUE; return AS_NORM; #ifdef ROTATION case 'X': rotate = !rotate; /* FALL THROUGH */ #else case Ctl('x'): case 'x': case 'X': notincl("x"); return AS_ASK; #endif case 'l': case Ctl('l'): /* refresh screen */ if (art <= lastart) { reread = TRUE; clear(); do_fseek = TRUE; artline = topline; if (artline < 0) artline = 0; } return AS_NORM; case 'b': case Ctl('b'): /* back up a page */ if (art <= lastart) { ART_LINE target; reread = TRUE; clear(); do_fseek = TRUE; target = topline - (LINES - 2); artline = topline; do { artline--; } while (artline >= 0 && artline > target && vrdary(artline-1) >= 0); topline = artline; if (artline < 0) artline = 0; } return AS_NORM; case '!': /* shell escape */ if (escapade()) return AS_INP; return AS_ASK; case 'C': { cancel_article(); return AS_ASK; } case 'R': case 'r': { /* reply? */ reply(); return AS_ASK; } case 'F': case 'f': { /* followup command */ followup(); forcegrow = TRUE; /* recalculate lastart */ return AS_ASK; } case '|': case 'w': case 'W': case 's': case 'S': /* save command */ if (save_article() == SAVE_ABORT) return AS_INP; return AS_ASK; #ifdef DELAYMARK case 'Y': /* yank back M articles */ yankback(); art = firstart; /* from the beginning */ return AS_NORM; /* pretend nothing happened */ #endif #ifdef STRICTCR case '\n': fputs(badcr,stdout) FLUSH; return AS_ASK; #endif default: printf("\n%s",hforhelp) FLUSH; settle_down(); return AS_ASK; } } #ifdef MAILCALL /* see if there is any mail */ void setmail() { if (! (mailcount++)) { char *mailfile = filexp(getval("MAILFILE",MAILFILE)); if (stat(mailfile,&filestat) < 0 || !filestat.st_size || filestat.st_atime > filestat.st_mtime) mailcall = nullstr; else mailcall = "(Mail) "; } mailcount %= 10; /* check every 10 articles */ } #endif void setdfltcmd() { if (toread[ng]) { #ifdef ARTSEARCH if (srchahead) dfltcmd = "^Nnpq"; else #endif dfltcmd = "npq"; } else { if (art > lastart) dfltcmd = "qnp"; else dfltcmd = "npq"; } } !STUFFY!FUNK! echo Extracting art.c cat >art.c <<'!STUFFY!FUNK!' /* $Header: art.c,v 4.3 85/05/01 11:34:51 lwall Exp $ * * $Log: art.c,v $ * Revision 4.3 85/05/01 11:34:51 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "rn.h" #include "ngstuff.h" #include "head.h" #include "cheat.h" #include "help.h" #include "search.h" #include "artio.h" #include "ng.h" #include "bits.h" #include "final.h" #include "artstate.h" #include "rcstuff.h" #include "term.h" #include "sw.h" #include "util.h" #include "backpage.h" #include "intrp.h" #include "INTERN.h" #include "art.h" /* page_switch() return values */ #define PS_NORM 0 #define PS_ASK 1 #define PS_RAISE 2 #define PS_TOEND 3 bool special = FALSE; /* is next page special length? */ int slines = 0; /* how long to make page when special */ ART_LINE highlight = -1; /* next line to be highlighted */ char *restart = Nullch; /* if nonzero, the place where last */ /* line left off on line split */ char *blinebeg; /* where in buffer current line began */ ART_POS alinebeg; /* where in file current line began */ #ifdef INNERSEARCH ART_POS innersearch = 0; /* artpos of end of line we found */ /* for 'g' command */ ART_LINE isrchline = 0; /* last line to display */ bool hide_everything = FALSE; /* if set, do not write page now, */ /* but refresh when done with page */ COMPEX gcompex; /* in article search pattern */ #endif bool firstpage; /* is this the 1st page of article? */ void art_init() { ; } int do_article() { register char *s; ART_POS artsize; /* size in bytes of article */ char art_buf[LBUFLEN]; /* place for article lines */ bool hide_this_line = FALSE; /* hidden header line? */ ART_LINE linenum; /* line # on page, 1 origin */ #ifdef ULSMARTS bool under_lining = FALSE; /* are we underlining a word? */ #endif register char *bufptr = art_buf; /* pointer to input buffer */ register int outpos; /* column position of output */ static char prompt_buf[64]; /* place to hold prompt */ bool notesfiles = FALSE; /* might there be notesfiles junk? */ char oldmode = mode; #ifdef INNERSEARCH register int outputok; #endif if (fstat(artfp->_file,&filestat)) /* get article file stats */ return DA_CLEAN; artsize = filestat.st_size; /* from that get article size */ sprintf(prompt_buf, "%%sEnd of article %ld (of %ld)--what next? [%%s]", (long)art,(long)lastart); /* format prompt string */ prompt = prompt_buf; int_count = 0; /* interrupt count is 0 */ firstpage = (topline < 0); for (;;) { /* for each page */ assert(art == openart); if (do_fseek) { #ifdef ASYNC_PARSE parse_maybe(art); /* make sure header is ours */ #endif artpos = vrdary(artline); if (artpos < 0) artpos = -artpos; /* labs(), anyone? */ fseek(artfp,artpos,0); if (artpos < htype[PAST_HEADER].ht_minpos) in_header = SOME_LINE; do_fseek = FALSE; restart = Nullch; } if (firstpage) { if (firstline) { interp(art_buf, (sizeof art_buf), firstline); #ifdef CLEAREOL maybe_eol(); /* PWP */ #endif CLEAREOL fputs(art_buf,stdout) FLUSH; artopen(art); /* rewind article in case interp */ /* forced a header parse */ } else { ART_NUM i; #ifdef CLEAREOL maybe_eol(); /* PWP */ #endif CLEAREOL printf("Article %ld",(long)art); i = (((ART_NUM)toread[ng]) - 1 + was_read(art)); #ifdef DELAYMARK if (i || dmcount) { printf(" (%ld more",(long)i); if (dmcount) printf(" + %ld Marked to return)",(long)dmcount); putchar(')'); } #else if (i) printf(" (%ld more)",(long)i); #endif if (htype[NGS_LINE].ht_flags & HT_HIDE) printf(" in %s", ngname); fputs(":\n",stdout) FLUSH; } start_header(art); forcelast = FALSE; /* we will have our day in court */ restart = Nullch; artline = 0; /* start counting lines */ artpos = 0; vwtary(artline,artpos); /* remember pos in file */ } for (linenum=(firstpage?2:1); in_header || ( #ifdef INNERSEARCH innersearch ? innermore() : #endif linenum<(firstpage?initlines:(special?slines:LINES)) ); linenum++) { /* for each line on page */ if (int_count) { /* exit via interrupt? */ putchar('\n') FLUSH; /* get to left margin */ int_count = 0; /* reset interrupt count */ return DA_NORM; /* skip out of loops */ } if (restart) { /* did not finish last line? */ bufptr = restart; /* then start again here */ restart = Nullch; /* and reset the flag */ } else { /* not a restart */ if (fgets(art_buf,LBUFLEN,artfp)==Nullch) { /* if all done */ return DA_NORM; /* skip out of loops */ } bufptr = art_buf; /* so start at beginning */ art_buf[LBUFLEN-1] = '\0'; /* make sure string ends */ } blinebeg = bufptr; /* remember where we began */ alinebeg = artpos; /* both in buffer and file */ if (in_header && bufptr == art_buf) hide_this_line = parseline(art_buf,do_hiding,hide_this_line); else if (notesfiles && do_hiding && bufptr == art_buf && *art_buf == '#' && isupper(art_buf[1]) && art_buf[2] == ':' ) { fgets(art_buf,sizeof(art_buf),artfp); if (index(art_buf,'!') != Nullch) fgets(art_buf,sizeof(art_buf),artfp); htype[PAST_HEADER].ht_minpos = ftell(artfp); /* exclude notesfiles droppings */ hide_this_line = TRUE; /* and do not print either */ notesfiles = FALSE; } if (in_header && htype[in_header].ht_flags & HT_MAGIC) { if (in_header == NGS_LINE) { hide_this_line = (index(art_buf,',') == Nullch && do_hiding); } else if (in_header == EXPIR_LINE) { if (!(htype[EXPIR_LINE].ht_flags & HT_HIDE)) hide_this_line = (strlen(art_buf) < 10 && do_hiding); } } if (in_header == SUBJ_LINE && htype[SUBJ_LINE].ht_flags & HT_MAGIC) { /* is this the subject? */ int length; length = strlen(art_buf)-1; artline++; art_buf[length] = '\0'; /* wipe out newline */ #ifdef NOFIREWORKS no_ulfire(); #endif notesfiles = (instr(&art_buf[length-10]," - (nf") != Nullch); if (oldsubject) { length += 7; fputs("(SAME) ",stdout); oldsubject = FALSE; } if (length+UG > COLS) { /* rarely true */ linenum++; vwtary(artline,vrdary(artline-1)+COLS); artline++; } s = art_buf + 8; *s++ = '\0'; /* make into 2 strings */ #ifdef CLEAREOL maybe_eol(); /* PWP */ #endif CLEAREOL fputs(art_buf,stdout) FLUSH; /* print up through : */ if (!UG) putchar(' '); underprint(s); /* print subject underlined */ putchar('\n') FLUSH; /* and finish the line */ } else if (hide_this_line) { /* do not print line? */ linenum--; /* compensate for linenum++ */ if (!in_header) hide_this_line = FALSE; } else { /* just a normal line */ if (highlight==artline) { /* this line to be highlit? */ if (marking == STANDOUT) { #ifdef NOFIREWORKS if (erase_screen) no_sofire(); #endif standout(); } else { #ifdef NOFIREWORKS if (erase_screen) no_ulfire(); #endif underline(); } if (*bufptr == '\n') putchar(' '); } #ifdef INNERSEARCH outputok = !hide_everything; /* get it into register, hopefully */ #endif #ifdef CLEAREOL #ifdef INNERSEARCH if (outputok) #endif maybe_eol(); /* PWP */ #endif CLEAREOL for (outpos = 0; outpos < COLS; ) { /* while line has room */ if (*bufptr >= ' ') { /* normal char? */ #ifdef ULSMARTS if (*bufptr == '_') { if (bufptr[1] == '\b') { if (!under_lining && highlight!=artline #ifdef INNERSEARCH && outputok #endif ) { under_lining++; if (UG) { if (bufptr != buf && bufptr[-1] == ' ') { outpos--; backspace(); } } underline(); } bufptr += 2; } } else { if (under_lining) { under_lining = 0; un_underline(); if (UG) { if (*bufptr == ' ') goto skip_put; outpos++; } } } #endif #ifdef INNERSEARCH if (outputok) #endif { #ifdef ROTATION if (rotate && !in_header && isalpha(*bufptr)) { if ((*bufptr & 31) <= 13) putchar(*bufptr+13); else putchar(*bufptr-13); } else #endif putchar(*bufptr); } if (*UC && ((highlight==artline && marking == 1) #ifdef ULSMARTS || under_lining #endif )) { backspace(); underchar(); } skip_put: bufptr++; outpos++; } else if (*bufptr == '\n' || !*bufptr) { /* newline? */ #ifdef ULSMARTS if (under_lining) { under_lining = 0; un_underline(); } #endif #ifdef DEBUGGING if (debug & DEB_INNERSRCH && outpos < COLS - 6) { standout(); printf("%4d",artline); un_standout(); } #endif #ifdef INNERSEARCH if (outputok) #endif putchar('\n') FLUSH; restart = 0; outpos = 1000; /* signal normal \n */ } else if (*bufptr == '\t') { /* tab? */ #ifdef INNERSEARCH if (outputok) #endif putchar(*bufptr); bufptr++; outpos += 8 - outpos % 8; } else if (*bufptr == '\f') { /* form feed? */ #ifdef INNERSEARCH if (outputok) #endif fputs("^L",stdout); if (bufptr == blinebeg && highlight != artline) linenum = 32700; /* how is that for a magic number? */ bufptr++; outpos += 2; } else { /* other control char */ #ifdef INNERSEARCH if (outputok) #endif { putchar('^'); if (highlight == artline && *UC && marking == 1) { backspace(); underchar(); putchar(*bufptr+64); backspace(); underchar(); } else putchar(*bufptr+64); } bufptr++; outpos += 2; } } /* end of column loop */ if (outpos < 1000) {/* did line overflow? */ restart = bufptr; /* restart here next time */ if (AM) { /* automatic margins on tty? */ if (!XN && *bufptr == '\n') /* need we simulate XN? */ restart = 0; /* skip the newline */ } else { /* cursor just hangs there */ #ifdef INNERSEARCH if (outputok) #endif putchar('\n') FLUSH; /* so move it down ourselves */ if (*bufptr == '\n') restart = 0; /* simulate XN if need be */ } #ifdef CLEAREOL /* #ifdef INNERSEARCH if (outputok) #endif maybe_eol(); */ /* PWP *//* comment this out for now until I am sure it is needed*/ #endif CLEAREOL } /* handle normal end of output line formalities */ if (highlight == artline) { /* were we highlighting line? */ if (marking == STANDOUT) un_standout(); else un_underline(); highlight = -1; /* no more we are */ } artline++; /* count the line just printed */ if (artline - LINES + 1 > topline) /* did we just scroll top line off? */ topline = artline - LINES + 1; /* then recompute top line # */ } /* determine actual position in file */ if (restart) /* stranded somewhere in the buffer? */ artpos += restart - blinebeg; /* just calculate position */ else /* no, ftell will do */ artpos = ftell(artfp); /* so do ftell */ vwtary(artline,artpos); /* remember pos in file */ } /* end of line loop */ #ifdef INNERSEARCH innersearch = 0; if (hide_everything) { hide_everything = FALSE; *buf = Ctl('l'); goto fake_command; } #endif if (linenum >= 32700)/* did last line have formfeed? */ vwtary(artline-1,-vrdary(artline-1)); /* remember by negating pos in file */ special = FALSE; /* end of page, so reset page length */ firstpage = FALSE; /* and say it is not 1st time thru */ /* extra loop bombout */ if (artpos == artsize) /* did we just now reach EOF? */ return DA_NORM; /* avoid --MORE--(100%) */ /* not done with this article, so pretend we are a pager */ reask_pager: unflush_output(); /* disable any ^O in effect */ standout(); /* enter standout mode */ printf("--MORE--(%ld%%)",(long)(artpos*100/artsize)); un_standout(); /* leave standout mode */ fflush(stdout); /* reinp_pager: /* unused, commented for lint */ eat_typeahead(); #ifdef DEBUGGING if (debug & DEB_CHECKPOINTING) { printf("(%d %d %d)",checkcount,linenum,artline); fflush(stdout); } #endif if (checkcount >= docheckwhen && linenum == LINES && (artline > 40 || checkcount >= docheckwhen+10) ) { /* while he is reading a whole page */ /* in an article he is interested in */ checkcount = 0; checkpoint_rc(); /* update .newsrc */ } collect_subjects(); /* loads subject cache until */ /* input is pending */ mode = 'p'; getcmd(buf); if (errno) { if (LINES < 100 && !int_count) *buf = '\f';/* on CONT fake up refresh */ else { *buf = 'q'; /* on INTR or paper just quit */ } } carriage_return(); #ifndef CLEAREOL erase_eol(); /* and erase the prompt */ #else if (erase_screen && can_home_clear) /* PWP was here */ clear_rest(); else erase_eol(); /* and erase the prompt */ #endif CLEAREOL fflush(stdout); fake_command: /* used by innersearch */ /* parse and process pager command */ switch (page_switch()) { case PS_ASK: /* reprompt "--MORE--..." */ goto reask_pager; case PS_RAISE: /* reparse on article level */ mode = oldmode; return DA_RAISE; case PS_TOEND: /* fast pager loop exit */ mode = oldmode; return DA_TOEND; case PS_NORM: /* display more article */ break; } } /* end of page loop */ } /* process pager commands */ int page_switch() { register char *s; switch (*buf) { case 'd': case Ctl('d'): /* half page */ special = TRUE; slines = LINES / 2 + 1; if (marking && *blinebeg != '\f') { up_line(); highlight = --artline; restart = blinebeg; artpos = alinebeg; } return PS_NORM; case '!': /* shell escape */ escapade(); return PS_ASK; #ifdef INNERSEARCH case Ctl('i'): gline = 3; sprintf(cmd_buf,"^[^%c]",*blinebeg); compile(&gcompex,cmd_buf,TRUE,TRUE); goto caseG; case Ctl('g'): gline = 3; compile(&gcompex,"^Subject:",TRUE,TRUE); goto caseG; case 'g': /* in-article search */ if (!finish_command(FALSE))/* get rest of command */ return PS_ASK; s = buf+1; if (isspace(*s)) s++; if ((s = compile(&gcompex,s,TRUE,TRUE)) != Nullch) { /* compile regular expression */ printf("\n%s\n",s) FLUSH; return PS_ASK; } carriage_return(); erase_eol(); /* erase the prompt */ /* FALL THROUGH */ caseG: case 'G': { /* ART_LINE lines_to_skip = 0; */ ART_POS start_where; if (gline < 0 || gline > LINES-2) gline = LINES-2; #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("Start here? %d >=? %d\n",topline + gline + 1,artline) FLUSH; #endif if (*buf == Ctl('i') || topline+gline+1 >= artline) start_where = artpos; /* in case we had a line wrap */ else { start_where = vrdary(topline+gline+1); if (start_where < 0) start_where = -start_where; } if (start_where < htype[PAST_HEADER].ht_minpos) start_where = htype[PAST_HEADER].ht_minpos; fseek(artfp,(long)start_where,0); innersearch = 0; /* assume not found */ while (fgets(buf, sizeof buf, artfp) != Nullch) { /* lines_to_skip++; NOT USED NOW */ #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("Test %s",buf) FLUSH; #endif if (execute(&gcompex,buf) != Nullch) { innersearch = ftell(artfp); break; } } if (!innersearch) { fseek(artfp,artpos,0); fputs("(Not found)",stdout) FLUSH; return PS_ASK; } #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("On page? %ld <=? %ld\n",(long)innersearch,(long)artpos) FLUSH; #endif if (innersearch <= artpos) { /* already on page? */ if (innersearch < artpos) { artline = topline+1; while (vrdary(artline) < innersearch) artline++; } highlight = artline - 1; #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("@ %d\n",highlight) FLUSH; #endif topline = highlight - gline; if (topline < -1) topline = -1; *buf = '\f'; /* fake up a refresh */ innersearch = 0; return page_switch(); } else { /* who knows how many lines it is? */ do_fseek = TRUE; hide_everything = TRUE; } return PS_NORM; } #else case 'g': case 'G': case Ctl('g'): notincl("g"); return PS_ASK; #endif case '\n': /* one line */ special = TRUE; slines = 2; return PS_NORM; #ifdef ROTATION case 'X': rotate = !rotate; /* FALL THROUGH */ #endif case 'l': case '\f': /* refresh screen */ #ifdef DEBUGGING if (debug & DEB_INNERSRCH) { printf("Topline = %d",topline) FLUSH; gets(buf); } #endif clear(); do_fseek = TRUE; artline = topline; if (artline < 0) artline = 0; firstpage = (topline < 0); return PS_NORM; case 'b': case '\b': /* I like backspace for this -- PWP */ /* Leaving it undocumented in case */ /* I want to steal the key--LAW */ case Ctl('b'): { /* back up a page */ ART_LINE target; #ifndef CLEAREOL clear(); #else if (can_home_clear) /* if we can home do it -- PWP */ home_cursor(); else clear(); #endif CLEAREOL do_fseek = TRUE; /* reposition article file */ target = topline - (LINES - 2); artline = topline; do { artline--; } while (artline >= 0 && artline > target && vrdary(artline-1) >= 0); topline = artline; /* remember top line of screen */ /* (line # within article file) */ if (artline < 0) artline = 0; firstpage = (topline < 0); return PS_NORM; } case 'h': { /* help */ int cmd; if ((cmd = help_page()) > 0) pushchar(cmd); return PS_ASK; } case '\177': case '\0': /* treat del,break as 'n' */ *buf = 'n'; /* FALL THROUGH */ case 'k': case 'K': case 'n': case 'N': case Ctl('n'): case 's': case 'S': case 'u': case 'w': case 'W': case '|': mark_as_read(art); /* mark article as read */ /* FALL THROUGH */ case '#': case '$': case '&': case '-': case '.': case '/': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '=': case '?': case 'c': case 'C': case 'f': case 'F': case 'j': case Ctl('k'): case 'm': case 'M': case 'p': case 'P': case Ctl('p'): case 'Q': case 'r': case 'R': case Ctl('r'): case 'v': case 'Y': #ifndef ROTATION case 'x': case 'X': #endif case Ctl('x'): case '^': #ifdef ROTATION rotate = FALSE; #endif reread = FALSE; do_hiding = TRUE; if (index("nNpP",*buf) == Nullch && index("wWsS!&|/?123456789.",*buf) != Nullch) { setdfltcmd(); standout(); /* enter standout mode */ printf(prompt,mailcall,dfltcmd); /* print prompt, whatever it is */ un_standout(); /* leave standout mode */ putchar(' '); fflush(stdout); } return PS_RAISE; /* and pretend we were at end */ #ifdef ROTATION case 'x': rotate = TRUE; /* FALL THROUGH */ #endif case 'y': case Ctl('v'): /* I like emacs -- PWP */ /* Leaving it undocumented in case */ /* I want to steal the key--LAW */ case ' ': /* continue current article */ if (erase_screen) { /* -e? */ #ifndef CLEAREOL clear(); /* clear screen */ #else if (can_home_clear) /* if we can home do it -- PWP */ home_cursor(); else clear(); /* else clear screen */ #endif CLEAREOL if (*blinebeg != '\f') { restart = blinebeg; artline--; /* restart this line */ artpos = alinebeg; if (marking) /* and mark repeated line */ highlight = artline; } topline = artline; /* and remember top line of screen */ /* (line # within article file) */ } else if (marking && *blinebeg != '\f') { /* are we marking repeats? */ up_line(); /* go up one line */ highlight = --artline;/* and get ready to highlight */ restart = blinebeg; /* the old line */ artpos = alinebeg; } return PS_NORM; case 'q': /* quit this article? */ do_hiding = TRUE; return PS_TOEND; default: fputs(hforhelp,stdout) FLUSH; settle_down(); return PS_ASK; } } #ifdef INNERSEARCH bool innermore() { if (artpos < innersearch) { /* not even on page yet? */ #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("Not on page %ld < %ld\n",(long)artpos,(long)innersearch) FLUSH; #endif return TRUE; } if (artpos == innersearch) { /* just got onto page? */ isrchline = artline; /* remember first line after */ highlight = artline - 1; #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("There it is %ld = %ld, %d @ %d\n",(long)artpos, (long)innersearch,hide_everything,highlight) FLUSH; #endif if (hide_everything) { /* forced refresh? */ topline = highlight - gline; if (topline < -1) topline = -1; return FALSE; /* let refresh do it all */ } } #ifdef DEBUGGING if (debug & DEB_INNERSRCH) printf("Not far enough? %d search.c <<'!STUFFY!FUNK!' /* $Header: search.c,v 4.3 85/05/01 11:50:16 lwall Exp $ * * $Log: search.c,v $ * Revision 4.3 85/05/01 11:50:16 lwall * Baseline for release with 4.3bsd. * */ /* string search routines */ /* Copyright (c) 1981,1980 James Gosling */ /* Modified Aug. 12, 1981 by Tom London to include regular expressions as in ed. RE stuff hacked over by jag to correct a few major problems, mainly dealing with searching within the buffer rather than copying each line to a separate array. Newlines can now appear in RE's */ /* Ripped to shreds and glued back together to make a search package, * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.) * Changes include: * Buffer, window, and mlisp stuff gone. * Translation tables reduced to 1 table. * Expression buffer is now dynamically allocated. * Character classes now implemented with a bitmap. */ #include "EXTERN.h" #include "common.h" #include "util.h" #include "INTERN.h" #include "search.h" #ifndef BITSPERBYTE #define BITSPERBYTE 8 #endif #define BMAPSIZ (127 / BITSPERBYTE + 1) /* meta characters in the "compiled" form of a regular expression */ #define CBRA 2 /* \( -- begin bracket */ #define CCHR 4 /* a vanilla character */ #define CDOT 6 /* . -- match anything except a newline */ #define CCL 8 /* [...] -- character class */ #define NCCL 10 /* [^...] -- negated character class */ #define CDOL 12 /* $ -- matches the end of a line */ #define CEND 14 /* The end of the pattern */ #define CKET 16 /* \) -- close bracket */ #define CBACK 18 /* \N -- backreference to the Nth bracketed string */ #define CIRC 20 /* ^ matches the beginning of a line */ #define WORD 32 /* matches word character \w */ #define NWORD 34 /* matches non-word characer \W */ #define WBOUND 36 /* matches word boundary \b */ #define NWBOUND 38 /* matches non-(word boundary) \B */ #define STAR 01 /* * -- Kleene star, repeats the previous REas many times as possible; the value ORs with the other operator types */ #define ASCSIZ 0200 typedef char TRANSTABLE[ASCSIZ]; static TRANSTABLE trans = { 0000,0001,0002,0003,0004,0005,0006,0007, 0010,0011,0012,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0024,0025,0026,0027, 0030,0031,0032,0033,0034,0035,0036,0037, 0040,0041,0042,0043,0044,0045,0046,0047, 0050,0051,0052,0053,0054,0055,0056,0057, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0072,0073,0074,0075,0076,0077, 0100,0101,0102,0103,0104,0105,0106,0107, 0110,0111,0112,0113,0114,0115,0116,0117, 0120,0121,0122,0123,0124,0125,0126,0127, 0130,0131,0132,0133,0134,0135,0136,0137, 0140,0141,0142,0143,0144,0145,0146,0147, 0150,0151,0152,0153,0154,0155,0156,0157, 0160,0161,0162,0163,0164,0165,0166,0167, 0170,0171,0172,0173,0174,0175,0176,0177, }; static bool folding = FALSE; static int err; static char *FirstCharacter; void search_init() { #ifdef UNDEF register int i; for (i = 0; i < ASCSIZ; i++) trans[i] = i; #else ; #endif } void init_compex(compex) register COMPEX *compex; { /* the following must start off zeroed */ compex->eblen = 0; compex->brastr = Nullch; } void free_compex(compex) register COMPEX *compex; { if (compex->eblen) { free(compex->expbuf); compex->eblen = 0; } if (compex->brastr) { free(compex->brastr); compex->brastr = Nullch; } } static char *gbr_str = Nullch; static int gbr_siz = 0; char * getbracket(compex,n) register COMPEX *compex; int n; { int length = compex->braelist[n] - compex->braslist[n]; if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0) return nullstr; growstr(&gbr_str, &gbr_siz, length+1); safecpy(gbr_str, compex->braslist[n], length+1); return gbr_str; } void case_fold(which) int which; { register int i; if (which != folding) { if (which) { for (i = 'A'; i <= 'Z'; i++) trans[i] = tolower(i); } else { for (i = 'A'; i <= 'Z'; i++) trans[i] = i; } folding = which; } } /* Compile the given regular expression into a [secret] internal format */ char * compile (compex, strp, RE, fold) register COMPEX *compex; register char *strp; int RE; int fold; { register int c; register char *ep; char *lastep; char bracket[NBRA], *bracketp; char **alt = compex->alternatives; char *retmes = "Badly formed search string"; case_fold(compex->do_folding = fold); if (!compex->eblen) { compex->expbuf = safemalloc(84); compex->eblen = 80; } ep = compex->expbuf; /* point at expression buffer */ *alt++ = ep; /* first alternative starts here */ bracketp = bracket; /* first bracket goes here */ if (*strp == 0) { /* nothing to compile? */ if (*ep == 0) /* nothing there yet? */ return "Null search string"; return Nullch; /* just keep old expression */ } compex->nbra = 0; /* no brackets yet */ lastep = 0; for (;;) { if (ep - compex->expbuf >= compex->eblen) grow_eb(compex); c = *strp++; /* fetch next char of pattern */ if (c == 0) { /* end of pattern? */ if (bracketp != bracket) { /* balanced brackets? */ #ifdef VERBOSE retmes = "Unbalanced parens"; #endif goto cerror; } *ep++ = CEND; /* terminate expression */ *alt++ = 0; /* terminal alternative list */ /* compex->eblen = ep - compex->expbuf + 1; compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */ return Nullch; /* return success */ } if (c != '*') lastep = ep; if (!RE) { /* just a normal search string? */ *ep++ = CCHR; /* everything is a normal char */ *ep++ = c; } else /* it is a regular expression */ switch (c) { case '\\': /* meta something */ switch (c = *strp++) { case '(': if (compex->nbra >= NBRA) { #ifdef VERBOSE retmes = "Too many parens"; #endif goto cerror; } *bracketp++ = ++compex->nbra; *ep++ = CBRA; *ep++ = compex->nbra; break; case '|': if (bracketp>bracket) { #ifdef VERBOSE retmes = "No \\| in parens"; /* Alas! */ #endif goto cerror; } *ep++ = CEND; *alt++ = ep; break; case ')': if (bracketp <= bracket) { #ifdef VERBOSE retmes = "Unmatched right paren"; #endif goto cerror; } *ep++ = CKET; *ep++ = *--bracketp; break; case 'w': *ep++ = WORD; break; case 'W': *ep++ = NWORD; break; case 'b': *ep++ = WBOUND; break; case 'B': *ep++ = NWBOUND; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *ep++ = CBACK; *ep++ = c - '0'; break; default: *ep++ = CCHR; if (c == '\0') goto cerror; *ep++ = c; break; } break; case '.': *ep++ = CDOT; continue; case '*': if (lastep == 0 || *lastep == CBRA || *lastep == CKET || *lastep == CIRC || (*lastep&STAR)|| *lastep>NWORD) goto defchar; *lastep |= STAR; continue; case '^': if (ep != compex->expbuf && ep[-1] != CEND) goto defchar; *ep++ = CIRC; continue; case '$': if (*strp != 0 && (*strp != '\\' || strp[1] != '|')) goto defchar; *ep++ = CDOL; continue; case '[': { /* character class */ register int i; if (ep - compex->expbuf >= compex->eblen - BMAPSIZ) grow_eb(compex); /* reserve bitmap */ for (i = BMAPSIZ; i; --i) ep[i] = 0; if ((c = *strp++) == '^') { c = *strp++; *ep++ = NCCL; /* negated */ } else *ep++ = CCL; /* normal */ i = 0; /* remember oldchar */ do { if (c == '\0') { #ifdef VERBOSE retmes = "Missing ]"; #endif goto cerror; } if (*strp == '-' && *(++strp)) i = *strp++; else i = c; while (c <= i) { ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE); if (fold && isalpha(c)) ep[(c ^ 32) / BITSPERBYTE] |= 1 << ((c ^ 32) % BITSPERBYTE); /* set the other bit too */ c++; } } while ((c = *strp++) != ']'); ep += BMAPSIZ; continue; } defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: compex->expbuf[0] = 0; compex->nbra = 0; return retmes; } void grow_eb(compex) register COMPEX *compex; { compex->eblen += 80; compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4); } char * execute (compex, addr) register COMPEX *compex; char *addr; { register char *p1 = addr; register char *trt = trans; register int c; if (addr == Nullch) return Nullch; if (compex->nbra) { /* any brackets? */ for (c = 0; c <= compex->nbra; c++) compex->braslist[c] = compex->braelist[c] = Nullch; if (compex->brastr) free(compex->brastr); compex->brastr = savestr(p1); /* in case p1 is not static */ p1 = compex->brastr; /* ! */ } case_fold(compex->do_folding); /* make sure table is correct */ FirstCharacter = p1; /* for ^ tests */ if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) { c = trt[compex->expbuf[1]]; /* fast check for first character */ do { if (trt[*p1] == c && advance (compex, p1, compex->expbuf)) return p1; p1++; } while (*p1 && !err); return Nullch; } else { /* regular algorithm */ do { register char **alt = compex->alternatives; while (*alt) { if (advance (compex, p1, *alt++)) return p1; } p1++; } while (*p1 && !err); return Nullch; } } /* advance the match of the regular expression starting at ep along the string lp, simulates an NDFSA */ bool advance (compex, lp, ep) register COMPEX *compex; register char *ep; register char *lp; { register char *curlp; register char *trt = trans; register int i; while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET) switch (*ep++) { case CCHR: if (trt[*ep++] != trt[*lp]) return FALSE; lp++; continue; case CDOT: if (*lp == '\n') return FALSE; lp++; continue; case CDOL: if (!*lp || *lp == '\n') continue; return FALSE; case CIRC: if (lp == FirstCharacter || lp[-1]=='\n') continue; return FALSE; case WORD: if (isalnum(*lp)) { lp++; continue; } return FALSE; case NWORD: if (!isalnum(*lp)) { lp++; continue; } return FALSE; case WBOUND: if ((lp == FirstCharacter || !isalnum(lp[-1])) != (!*lp || !isalnum(*lp)) ) continue; return FALSE; case NWBOUND: if ((lp == FirstCharacter || !isalnum(lp[-1])) == (!*lp || !isalnum(*lp))) continue; return FALSE; case CEND: return TRUE; case CCL: if (cclass (ep, *lp, 1)) { ep += BMAPSIZ; lp++; continue; } return FALSE; case NCCL: if (cclass (ep, *lp, 0)) { ep += BMAPSIZ; lp++; continue; } return FALSE; case CBRA: compex->braslist[*ep++] = lp; continue; case CKET: i = *ep++; compex->braelist[i] = lp; compex->braelist[0] = lp; compex->braslist[0] = compex->braslist[i]; continue; case CBACK: if (compex->braelist[i = *ep++] == 0) { fputs("bad braces\n",stdout) FLUSH; err = TRUE; return FALSE; } if (backref (compex, i, lp)) { lp += compex->braelist[i] - compex->braslist[i]; continue; } return FALSE; case CBACK | STAR: if (compex->braelist[i = *ep++] == 0) { fputs("bad braces\n",stdout) FLUSH; err = TRUE; return FALSE; } curlp = lp; while (backref (compex, i, lp)) { lp += compex->braelist[i] - compex->braslist[i]; } while (lp >= curlp) { if (advance (compex, lp, ep)) return TRUE; lp -= compex->braelist[i] - compex->braslist[i]; } continue; case CDOT | STAR: curlp = lp; while (*lp++ && lp[-1] != '\n'); goto star; case WORD | STAR: curlp = lp; while (*lp++ && isalnum(lp[-1])); goto star; case NWORD | STAR: curlp = lp; while (*lp++ && !isalnum(lp[-1])); goto star; case CCHR | STAR: curlp = lp; while (*lp++ && trt[lp[-1]] == trt[*ep]); ep++; goto star; case CCL | STAR: case NCCL | STAR: curlp = lp; while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR))); ep += BMAPSIZ; goto star; star: do { lp--; if (advance (compex, lp, ep)) return TRUE; } while (lp > curlp); return FALSE; default: fputs("Badly compiled pattern\n",stdout) FLUSH; err = TRUE; return -1; } if (*ep == CEND || *ep == CDOL) { return TRUE; } return FALSE; } bool backref (compex, i, lp) register COMPEX *compex; register int i; register char *lp; { register char *bp; bp = compex->braslist[i]; while (*lp && *bp == *lp) { bp++; lp++; if (bp >= compex->braelist[i]) return TRUE; } return FALSE; } bool cclass (set, c, af) register char *set; register int c; { c &= 0177; #if BITSPERBYTE == 8 if (set[c >> 3] & 1 << (c & 7)) #else if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE)) #endif return af; return !af; } !STUFFY!FUNK! echo Extracting ngstuff.c cat >ngstuff.c <<'!STUFFY!FUNK!' /* $Header: ngstuff.c,v 4.3 85/05/01 11:45:03 lwall Exp $ * * $Log: ngstuff.c,v $ * Revision 4.3 85/05/01 11:45:03 lwall * Baseline for release with 4.3bsd. * */ #include "EXTERN.h" #include "common.h" #include "term.h" #include "util.h" #include "ng.h" #include "bits.h" #include "intrp.h" #include "cheat.h" #include "head.h" #include "final.h" #include "sw.h" #include "INTERN.h" #include "ngstuff.h" void ngstuff_init() { ; } /* do a shell escape */ int escapade() { register char *s; bool interactive = (buf[1] == FINISHCMD); bool docd; char whereiam[256]; if (!finish_command(interactive)) /* get remainder of command */ return -1; s = buf+1; docd = *s != '!'; if (!docd) { s++; } else { getwd(whereiam); if (chdir(cwd)) { printf(nocd,cwd) FLUSH; sig_catcher(0); } } while (*s == ' ') s++; /* skip leading spaces */ interp(cmd_buf, (sizeof cmd_buf), s);/* interpret any % escapes */ resetty(); /* make sure tty is friendly */ doshell(Nullch,cmd_buf); /* invoke the shell */ noecho(); /* and make terminal */ crmode(); /* unfriendly again */ if (docd) { if (chdir(whereiam)) { printf(nocd,whereiam) FLUSH; sig_catcher(0); } } #ifdef MAILCALL; mailcount = 0; /* force recheck */ #endif return 0; } /* process & command */ int switcheroo() { if (!finish_command(TRUE)) /* get rest of command */ return -1; /* if rubbed out, try something else */ if (!buf[1]) pr_switches(); #ifdef PUSHBACK else if (buf[1] == '&') { if (!buf[2]) { page_init(); show_macros(); } else { char tmpbuf[LBUFLEN]; register char *s; for (s=buf+2; isspace(*s); s++); mac_line(s,tmpbuf,(sizeof tmpbuf)); } } #endif else { bool docd = (instr(buf,"-d") != Nullch); char whereami[256]; if (docd) getwd(whereami); sw_list(buf+1); if (docd) { cwd_check(); if (chdir(whereami)) { /* -d does chdirs */ printf(nocd,whereami) FLUSH; sig_catcher(0); } } } return 0; } /* process range commands */ int numnum() { ART_NUM min, max; char *cmdlst = Nullch; register char *s, *c; ART_NUM oldart = art; char tmpbuf[LBUFLEN]; bool justone = TRUE; /* assume only one article */ if (!finish_command(TRUE)) /* get rest of command */ return NN_INP; if (lastart < 1) { fputs("\nNo articles\n",stdout) FLUSH; return NN_ASK; } #ifdef ARTSRCH if (srchahead) srchahead = -1; #endif for (s=buf; *s && (isdigit(*s) || index(" ,-.$",*s)); s++) if (!isdigit(*s)) justone = FALSE; if (*s) { cmdlst = savestr(s); justone = FALSE; } else if (!justone) cmdlst = savestr("m"); *s++ = ','; *s = '\0'; safecpy(tmpbuf,buf,LBUFLEN); for (s = tmpbuf; c = index(s,','); s = ++c) { *c = '\0'; if (*s == '.') min = oldart; else min = atol(s); if (minlastart) { max = lastart; if (min > max) min = max; printf("(Last article is %ld)\n",(long)lastart) FLUSH; pad(just_a_sec/3); } if (max < min) { fputs("\nBad range\n",stdout) FLUSH; if (cmdlst) free(cmdlst); return NN_ASK; } if (justone) { art = min; return NN_REREAD; } check_first(min); for (art=min; art<=max; art++) { if (perform(cmdlst,TRUE)) { #ifdef VERBOSE IF(verbose) printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH; ELSE #endif #ifdef TERSE printf("\n(Intr at %ld)\n",(long)art) FLUSH; #endif if (cmdlst) free(cmdlst); return NN_ASK; } } } art = oldart; if (cmdlst) free(cmdlst); return NN_NORM; } int perform(cmdlst,toplevel) register char *cmdlst; int toplevel; { register int ch; if (toplevel) { printf("%-6ld",art); fflush(stdout); } for (; ch = *cmdlst; cmdlst++) { if (isspace(ch) || ch == ':') continue; if (ch == 'j') { mark_as_read(art); #ifdef VERBOSE IF(verbose) fputs("\tJunked",stdout); #endif } else if (ch == 'm') { unmark_as_read(art); #ifdef VERBOSE IF(verbose) fputs("\tMarked unread",stdout); #endif } else if (ch == 'M') { #ifdef DELAYMARK delay_unmark(art); #ifdef VERBOSE IF(verbose) fputs("\tWill return",stdout); #endif #else notincl("M"); return -1; #endif } else if (ch == '=') { printf("\t%s",fetchsubj(art,FALSE,FALSE)); #ifdef VERBOSE IF(verbose) ; ELSE #endif putchar('\n') FLUSH; /* ghad! */ } else if (ch == 'C') { #ifdef ASYNC_PARSE printf("\t%sancelled",(cancel_article() ? "Not c" : "C")); #else notincl("C"); return -1; #endif } else if (ch == '%') { #ifdef ASYNC_PARSE char tmpbuf[512]; cmdlst = dointerp(tmpbuf, (sizeof tmpbuf), cmdlst,":"); if (*cmdlst != ':') --cmdlst; if (perform(tmpbuf,FALSE)) return -1; #else notincl("%"); return -1; #endif } else if (index("!&sSwW|",ch)) { cmdlst = cpytill(buf,cmdlst,':') - 1; /* we now have the command in buf */ if (ch == '!') { escapade(); #ifdef VERBOSE IF(verbose) fputs("\tShell escaped",stdout); #endif } else if (ch == '&') { switcheroo(); #ifdef VERBOSE IF(verbose) fputs("\tSwitched",stdout); #endif } else { putchar('\t'); save_article(); } } else { printf("\t???%s\n",cmdlst); return -1; } #ifdef VERBOSE fflush(stdout); #endif } if (toplevel) { #ifdef VERBOSE IF(verbose) putchar('\n') FLUSH; ELSE #endif #ifdef TERSE putchar(' '); #endif } return 0; } !STUFFY!FUNK! echo Extracting makedist cat >makedist <<'!STUFFY!FUNK!' #!/bin/sh # $Header: makedist,v 4.3 85/05/01 11:42:35 lwall Exp $ # # $Log: makedist,v $ # Revision 4.3 85/05/01 11:42:35 lwall # Baseline for release with 4.3bsd. # rm -f kit*.list manifake kitlists manimake makekit kit*.list !STUFFY!FUNK! echo "" echo "End of kit 4 (of 9)" cat /dev/null >kit4isdone config=true for iskit in 1 2 3 4 5 6 7 8 9; do if test -f kit${iskit}isdone; then echo "You have run kit ${iskit}." else echo "You still need to run kit ${iskit}." config=false fi done case $config in true) echo "You have run all your kits. Please read README and then type Configure." chmod 755 Configure ;; esac : I do not append .signature, but someone might mail this. exit