home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume1 / rn / part04 < prev    next >
Encoding:
Text File  |  1986-11-30  |  61.8 KB  |  2,808 lines

  1. Date: Tue, 7 May 85 13:49:10 pdt
  2. From: allegra!sdcrdcf!RDCF.SDC.UUCP!lwall (Larry Wall)
  3. Newsgroups: mod.sources
  4. Subject: rn version 4.3 (kit 4 of 9)
  5. Reply-To: lwall@sdcrdcf.UUCP
  6. Organization: System Development Corporation R&D, Santa Monica
  7.  
  8. #! /bin/sh
  9.  
  10. # Make a new directory for the rn sources, cd to it, and run kits 1 thru 9 
  11. # through sh.  When all 9 kits have been run, read README.
  12.  
  13. echo "This is rn kit 4 (of 9).  If kit 4 is complete, the line"
  14. echo '"'"End of kit 4 (of 9)"'" will echo at the end.'
  15. echo ""
  16. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  17. echo Extracting ng.c
  18. cat >ng.c <<'!STUFFY!FUNK!'
  19. /* $Header: ng.c,v 4.3 85/05/01 11:43:43 lwall Exp $
  20.  *
  21.  * $Log:    ng.c,v $
  22.  * Revision 4.3  85/05/01  11:43:43  lwall
  23.  * Baseline for release with 4.3bsd.
  24.  * 
  25.  */
  26.  
  27. #include "EXTERN.h"
  28. #include "common.h"
  29. #include "rn.h"
  30. #include "term.h"
  31. #include "final.h"
  32. #include "util.h"
  33. #include "artsrch.h"
  34. #include "cheat.h"
  35. #include "help.h"
  36. #include "kfile.h"
  37. #include "rcstuff.h"
  38. #include "head.h"
  39. #include "artstate.h"
  40. #include "bits.h"
  41. #include "art.h"
  42. #include "artio.h"
  43. #include "ngstuff.h"
  44. #include "intrp.h"
  45. #include "respond.h"
  46. #include "ngdata.h"
  47. #include "backpage.h"
  48. #include "rcln.h"
  49. #include "last.h"
  50. #include "INTERN.h"
  51. #include "ng.h"
  52. #include "artstate.h"            /* somebody has to do it */
  53.  
  54. /* art_switch() return values */
  55.  
  56. #define AS_NORM 0
  57. #define AS_INP 1
  58. #define AS_ASK 2
  59. #define AS_CLEAN 3
  60.  
  61. ART_NUM recent_art = 0;        /* previous article # for '-' command */
  62. ART_NUM curr_art = 0;                /* current article # */
  63. int exit_code = NG_NORM;
  64.  
  65. void
  66. ng_init()
  67. {
  68.  
  69. #ifdef KILLFILES
  70.     open_kfile(KF_GLOBAL);
  71. #endif
  72. }
  73.  
  74. /* do newsgroup on line ng with name ngname */
  75.  
  76. /* assumes that we are chdir'ed to SPOOL, and assures that that is
  77.  * still true upon return, but chdirs to SPOOL/ngname in between
  78.  *
  79.  * If you can understand this routine, you understand most of the program.
  80.  * The basic structure is:
  81.  *    for each desired article
  82.  *        for each desired page
  83.  *            for each line on page
  84.  *                if we need another line from file
  85.  *                    get it
  86.  *                    if it's a header line
  87.  *                        do special things
  88.  *                for each column on page
  89.  *                    put out a character
  90.  *                end loop
  91.  *            end loop
  92.  *        end loop
  93.  *    end loop
  94.  *
  95.  *    (Actually, the pager is in another routine.)
  96.  *
  97.  * The chief problem is deciding what is meant by "desired".  Most of
  98.  * the messiness of this routine is due to the fact that people want
  99.  * to do unstructured things all the time.  I have used a few judicious
  100.  * goto's where I thought it improved readability.  The rest of the messiness
  101.  * arises from trying to be both space and time efficient.  Have fun.
  102.  */
  103.  
  104. int
  105. do_newsgroup(start_command)
  106. char *start_command;            /* command to fake up first */
  107. {
  108.     char oldmode = mode;
  109.     register long i;            /* scratch */
  110.     int skipstate;            /* how many unavailable articles */
  111.                     /*   have we skipped already? */
  112.     
  113.     char *whatnext = "%sWhat next? [%s]";
  114.  
  115. #ifdef ARTSEARCH
  116.     srchahead = (scanon && ((ART_NUM)toread[ng]) >= scanon ? -1 : 0);
  117.                     /* did they say -S? */
  118. #endif
  119.     
  120.     mode = 'a';
  121.     recent_art = curr_art = 0;
  122.     exit_code = NG_NORM;
  123.     if (eaccess(ngdir,5)) {        /* directory read protected? */
  124.     if (eaccess(ngdir,0)) {
  125. #ifdef VERBOSE
  126.         IF(verbose)
  127.         printf("\nNewsgroup %s does not have a spool directory!\n",
  128.             ngname) FLUSH;
  129.         ELSE
  130. #endif
  131. #ifdef TERSE
  132.         printf("\nNo spool for %s!\n",ngname) FLUSH;
  133. #endif
  134. #ifdef CATCHUP
  135.         catch_up(ng);
  136. #endif
  137.         toread[ng] = TR_NONE;
  138.     }
  139.     else {
  140. #ifdef VERBOSE
  141.         IF(verbose)
  142.         printf("\nNewsgroup %s is not currently accessible.\n",
  143.             ngname) FLUSH;
  144.         ELSE
  145. #endif
  146. #ifdef TERSE
  147.         printf("\n%s not readable.\n",ngname) FLUSH;
  148. #endif
  149.         toread[ng] = TR_NONE;    /* make this newsgroup invisible */
  150.                     /* (temporarily) */
  151.     }
  152.     mode = oldmode;
  153.     return -1;
  154.     }
  155.  
  156.     /* chdir to newsgroup subdirectory */
  157.  
  158.     if (chdir(ngdir)) {
  159.     printf(nocd,ngdir) FLUSH;
  160.     mode = oldmode;
  161.     return -1;
  162.     }
  163.  
  164. #ifdef CACHESUBJ
  165.     subj_list = Null(char **);        /* no subject list till needed */
  166. #endif
  167.     
  168.     /* initialize control bitmap */
  169.  
  170.     if (initctl()) {
  171.     mode = oldmode;
  172.     return -1;
  173.     }
  174.  
  175.     /* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */
  176.     
  177.     in_ng = TRUE;            /* tell the world we are here */
  178.     forcelast = TRUE;            /* if 0 unread, do not bomb out */
  179.     art=firstart;
  180.     
  181.     /* remember what newsgroup we were in for sake of posterity */
  182.  
  183.     writelast();
  184.  
  185.     /* do they want a special top line? */
  186.  
  187.     firstline = getval("FIRSTLINE",Nullch);
  188.  
  189.     /* see if there are any special searches to do */
  190.  
  191. #ifdef KILLFILES
  192.     open_kfile(KF_LOCAL);
  193. #ifdef VERBOSE
  194.     IF(verbose)
  195.     kill_unwanted(firstart,"Looking for articles to kill...\n\n",TRUE);
  196.     ELSE
  197. #endif
  198. #ifdef TERSE
  199.     kill_unwanted(firstart,"Killing...\n\n",TRUE);
  200. #endif
  201. #endif
  202.     
  203.     /* now read each unread article */
  204.  
  205.     rc_changed = doing_ng = TRUE;    /* enter the twilight zone */
  206.     skipstate = 0;            /* we have not skipped anything (yet) */
  207.     checkcount = 0;            /* do not checkpoint for a while */
  208.     do_fseek = FALSE;            /* start 1st article at top */
  209.     if (art > lastart)
  210.     art=firstart;            /* init the for loop below */
  211.     for (; art<=lastart+1; ) {        /* for each article */
  212.  
  213.     /* do we need to "grow" the newsgroup? */
  214.  
  215.     if (art > lastart || forcegrow)
  216.         grow_ctl();
  217.     check_first(art);        /* make sure firstart is still 1st */
  218.     if (start_command) {        /* fake up an initial command? */
  219.         prompt = whatnext;
  220.         strcpy(buf,start_command);
  221.         free(start_command);
  222.         start_command = Nullch;
  223.         art = lastart+1;
  224.         goto article_level;
  225.     }
  226.     if (art>lastart) {        /* are we off the end still? */
  227.         ART_NUM ucount = 0;        /* count of unread articles left */
  228.  
  229.         for (i=firstart; i<=lastart; i++)
  230.         if (!(ctl_read(i)))
  231.             ucount++;        /* count the unread articles */
  232. #ifdef DEBUGGING
  233.         /*NOSTRICT*/
  234.         if (debug && ((ART_NUM)toread[ng]) != ucount)
  235.         printf("(toread=%ld sb %ld)",(long)toread[ng],(long)ucount)
  236.           FLUSH;
  237. #endif
  238.         /*NOSTRICT*/
  239.         toread[ng] = (ART_UNREAD)ucount;    /* this is perhaps pointless */
  240.         art = lastart + 1;        /* keep bitmap references sane */
  241.         if (art != curr_art) {
  242.         recent_art = curr_art;
  243.                     /* remember last article # (for '-') */
  244.         curr_art = art;      /* remember this article # */
  245.         }
  246.         if (erase_screen)
  247.         clear();            /* clear the screen */
  248.         else
  249.         fputs("\n\n",stdout) FLUSH;
  250. #ifdef VERBOSE
  251.         IF(verbose)
  252.         printf("End of newsgroup %s.",ngname);
  253.                     /* print pseudo-article */
  254.         ELSE
  255. #endif
  256. #ifdef TERSE
  257.         printf("End of %s",ngname);
  258. #endif
  259.         if (ucount) {
  260.         printf("  (%ld article%s still unread)",
  261.             (long)ucount,ucount==1?nullstr:"s");
  262.         }
  263.         else {
  264.         if (!forcelast)
  265.             goto cleanup;    /* actually exit newsgroup */
  266.         }
  267.         prompt = whatnext;
  268. #ifdef ARTSEARCH
  269.         srchahead = 0;        /* no more subject search mode */
  270. #endif
  271.         fputs("\n\n",stdout) FLUSH;
  272.         skipstate = 0;        /* back to none skipped */
  273.     }
  274.     else if (!reread && was_read(art)) {
  275.                     /* has this article been read? */
  276.         art++;            /* then skip it */
  277.         continue;
  278.     }
  279.     else if
  280.       (!reread && !was_read(art)
  281.         && artopen(art) == Nullfp) {    /* never read it, & cannot find it? */
  282.         if (errno != ENOENT) {    /* has it not been deleted? */
  283. #ifdef VERBOSE
  284.         IF(verbose)
  285.             printf("\n(Article %ld exists but is unreadable.)\n",
  286.             (long)art) FLUSH;
  287.         ELSE
  288. #endif
  289. #ifdef TERSE
  290.             printf("\n(%ld unreadable.)\n",(long)art) FLUSH;
  291. #endif
  292.         skipstate = 0;
  293.         sleep(2);
  294.         }
  295.         switch(skipstate++) {
  296.         case 0:
  297.         clear();
  298. #ifdef VERBOSE
  299.         IF(verbose)
  300.             fputs("Skipping unavailable article",stdout);
  301.         ELSE
  302. #endif
  303. #ifdef TERSE
  304.             fputs("Skipping",stdout);
  305. #endif
  306.         for (i = just_a_sec/3; i; --i)
  307.             putchar(PC);
  308.         fflush(stdout);
  309.         sleep(1);
  310.         break;
  311.         case 1:
  312.         fputs("..",stdout);
  313.         fflush(stdout);
  314.         break;
  315.         default:
  316.         putchar('.');
  317.         fflush(stdout);
  318. #define READDIR
  319. #ifdef READDIR
  320.         {            /* fast skip patch */
  321.             ART_NUM newart;
  322.             
  323.             if (! (newart=getngmin(".",art)))
  324.             newart = lastart+1;
  325.             for (i=art; i<newart; i++)
  326.             oneless(i);
  327.             art = newart - 1;
  328.         }
  329. #endif
  330.         break;
  331.         }
  332.         oneless(art);        /* mark deleted as read */
  333.         art++;            /* try next article */
  334.         continue;
  335.     }
  336.     else {                /* we have a real live article */
  337.         skipstate = 0;        /* back to none skipped */
  338.         if (art != curr_art) {
  339.         recent_art = curr_art;
  340.                     /* remember last article # (for '-') */
  341.         curr_art = art;      /* remember this article # */
  342.         }
  343.         if (!do_fseek) {        /* starting at top of article? */
  344.         artline = 0;        /* start at the beginning */
  345.         topline = -1;        /* and remember top line of screen */
  346.                     /*  (line # within article file) */
  347.         }
  348.         clear();            /* clear screen */
  349.         artopen(art);        /* make sure article file is open */
  350.         if (artfp == Nullfp) {    /* could not find article? */
  351.         printf("Article %ld of %s is not available.\n\n",
  352.             (long)art,ngname) FLUSH;
  353.         prompt = whatnext;
  354. #ifdef ARTSEARCH
  355.         srchahead = 0;
  356. #endif
  357.         }
  358.         else {            /* found it, so print it */
  359.         switch (do_article()) {
  360.         case DA_CLEAN:        /* quit newsgroup */
  361.             goto cleanup;
  362.         case DA_TOEND:        /* do not mark as read */
  363.             goto reask_article; 
  364.         case DA_RAISE:        /* reparse command at end of art */
  365.             goto article_level;
  366.         case DA_NORM:        /* normal end of article */
  367.             break;
  368.         }
  369.         }
  370.         mark_as_read(art);         /* mark current article as read */
  371.         reread = FALSE;
  372.         do_hiding = TRUE;
  373. #ifdef ROTATION
  374.         rotate = FALSE;
  375. #endif
  376.     }
  377.  
  378. /* if these gotos bother you, think of this as a little state machine */
  379.  
  380. reask_article:
  381. #ifdef MAILCALL
  382.     setmail();
  383. #endif
  384.     setdfltcmd();
  385. #ifdef CLEAREOL
  386.     if (erase_screen && can_home_clear)    /* PWP was here */
  387.         clear_rest();
  388. #endif CLEAREOL
  389.     unflush_output();        /* disable any ^O in effect */
  390.     standout();            /* enter standout mode */
  391.     printf(prompt,mailcall,dfltcmd);/* print prompt, whatever it is */
  392.     un_standout();            /* leave standout mode */
  393.     putchar(' ');
  394.     fflush(stdout);
  395. reinp_article:
  396.     eat_typeahead();
  397. #ifdef PENDING
  398.     look_ahead();            /* see what we can do in advance */
  399.     if (!input_pending())
  400.         collect_subjects();        /* loads subject cache until */
  401.                     /* input is pending */
  402. #endif
  403.     getcmd(buf);
  404.     if (errno || *buf == '\f') {
  405.         if (LINES < 100 && !int_count)
  406.         *buf = '\f';        /* on CONT fake up refresh */
  407.         else {
  408.         putchar('\n') FLUSH;        /* but only on a crt */
  409.         goto reask_article;
  410.         }
  411.     }
  412. article_level:
  413.  
  414.     /* parse and process article level command */
  415.  
  416.     switch (art_switch()) {
  417.     case AS_INP:            /* multichar command rubbed out */
  418.         goto reinp_article;
  419.     case AS_ASK:            /* reprompt "End of article..." */
  420.         goto reask_article;
  421.     case AS_CLEAN:            /* exit newsgroup */
  422.         goto cleanup;
  423.     case AS_NORM:            /* display article art */
  424.         break;
  425.     }
  426.     }                    /* end of article selection loop */
  427.     
  428. /* shut down newsgroup */
  429.  
  430. cleanup:
  431. #ifdef KILLFILES
  432.     kill_unwanted(firstart,"\nCleaning up...\n\n",FALSE);
  433.                     /* do cleanup from KILL file, if any */
  434. #endif
  435.     in_ng = FALSE;            /* leave newsgroup state */
  436.     if (artfp != Nullfp) {        /* article still open? */
  437.     fclose(artfp);            /* close it */
  438.     artfp = Nullfp;            /* and tell the world */
  439.     openart = 0;
  440.     }
  441.     putchar('\n') FLUSH;
  442.     yankback();                /* do a Y command */
  443.     restore_ng();            /* reconstitute .newsrc line */
  444.     doing_ng = FALSE;            /* tell sig_catcher to cool it */
  445.     free(ctlarea);            /* return the control area */
  446. #ifdef CACHESUBJ
  447.     if (subj_list) {
  448.     for (i=OFFSET(lastart); i>=0; --i)
  449.         if (subj_list[i])
  450.         free(subj_list[i]);
  451. #ifndef lint
  452.     free((char*)subj_list);
  453. #endif lint
  454.     }
  455. #endif
  456.     write_rc();                /* and update .newsrc */
  457.     rc_changed = FALSE;            /* tell sig_catcher it is ok */
  458.     if (chdir(spool)) {
  459.     printf(nocd,spool) FLUSH;
  460.     sig_catcher(0);
  461.     }
  462. #ifdef KILLFILES
  463.     if (localkfp) {
  464.     fclose(localkfp);
  465.     localkfp = Nullfp;
  466.     }
  467. #endif
  468.     mode = oldmode;
  469.     return exit_code;
  470. }                    /* Whew! */
  471.  
  472. /* decide what to do at the end of an article */
  473.  
  474. int
  475. art_switch()
  476. {
  477.     register ART_NUM i;
  478.       
  479.     setdef(buf,dfltcmd);
  480. #ifdef VERIFY
  481.     printcmd();
  482. #endif
  483.     switch (*buf) {
  484.     case 'p':            /* find previous unread article */
  485.     do {
  486.         if (art <= firstart)
  487.         break;
  488.         art--;
  489.     } while (was_read(art) || artopen(art) == Nullfp);
  490. #ifdef ARTSEARCH
  491.     srchahead = 0;
  492. #endif
  493.     return AS_NORM;
  494.     case 'P':            /* goto previous article */
  495.     if (art > absfirst)
  496.         art--;
  497.     else {
  498. #ifdef VERBOSE
  499.         IF(verbose)
  500.         fputs("\n\
  501. There are no articles prior to this one.\n\
  502. ",stdout) FLUSH;
  503.         ELSE
  504. #endif
  505. #ifdef TERSE
  506.         fputs("\nNo previous articles\n",stdout) FLUSH;
  507. #endif
  508.         return AS_ASK;
  509.     }
  510.     reread = TRUE;
  511. #ifdef ARTSEARCH
  512.     srchahead = 0;
  513. #endif
  514.     return AS_NORM;
  515.     case '-':
  516.     if (recent_art) {
  517.         art = recent_art;
  518.         reread = TRUE;
  519. #ifdef ARTSEARCH
  520.         srchahead = -(srchahead != 0);
  521. #endif
  522.         return AS_NORM;
  523.     }
  524.     else {
  525.         exit_code = NG_MINUS;
  526.         return AS_CLEAN;
  527.     }
  528.     case 'n':        /* find next unread article? */
  529.     if (art > lastart) {
  530.         if (toread[ng])
  531.         art = firstart;
  532.         else
  533.         return AS_CLEAN;
  534.     }
  535. #ifdef ARTSEARCH
  536.     else if (scanon && srchahead) {
  537.         *buf = Ctl('n');
  538.         goto normal_search;
  539.     }
  540. #endif
  541.     else
  542.         art++;
  543. #ifdef ARTSEARCH
  544.     srchahead = 0;
  545. #endif
  546.     return AS_NORM;
  547.     case 'N':            /* goto next article */
  548.     if (art > lastart)
  549.         art = absfirst;
  550.     else
  551.         art++;
  552.     if (art <= lastart)
  553.         reread = TRUE;
  554. #ifdef ARTSEARCH
  555.     srchahead = 0;
  556. #endif
  557.     return AS_NORM;
  558.     case '$':
  559.     art = lastart+1;
  560.     forcelast = TRUE;
  561. #ifdef ARTSEARCH
  562.     srchahead = 0;
  563. #endif
  564.     return AS_NORM;
  565.     case '1': case '2': case '3':    /* goto specified article */
  566.     case '4': case '5': case '6':    /* or do something with a range */
  567.     case '7': case '8': case '9': case '.':
  568.     forcelast = TRUE;
  569.     switch (numnum()) {
  570.     case NN_INP:
  571.         return AS_INP;
  572.     case NN_ASK:
  573.         return AS_ASK;
  574.     case NN_REREAD:
  575.         reread = TRUE;
  576. #ifdef ARTSEARCH
  577.         if (srchahead)
  578.         srchahead = -1;
  579. #endif
  580.         break;
  581.     case NN_NORM:
  582.         if (was_read(art)) {
  583.         art = firstart;
  584.         pad(just_a_sec/3);
  585.         }
  586.         else
  587.         return AS_ASK;
  588.         break;
  589.     }
  590.     return AS_NORM;
  591.     case Ctl('k'):
  592.     edit_kfile();
  593.     return AS_ASK;
  594.     case 'K':
  595.     case 'k':
  596.     case Ctl('n'): case Ctl('p'):
  597.     case '/': case '?':
  598. #ifdef ARTSEARCH
  599. normal_search:
  600.     {        /* search for article by pattern */
  601.     char cmd = *buf;
  602.     
  603.     reread = TRUE;        /* assume this */
  604.     switch (art_search(buf, (sizeof buf), TRUE)) {
  605.     case SRCH_ERROR:
  606.         return AS_ASK;
  607.     case SRCH_ABORT:
  608.         return AS_INP;
  609.     case SRCH_INTR:
  610. #ifdef VERBOSE
  611.         IF(verbose)
  612.         printf("\n(Interrupted at article %ld)\n",(long)art) FLUSH;
  613.         ELSE
  614. #endif
  615. #ifdef TERSE
  616.         printf("\n(Intr at %ld)\n",(long)art) FLUSH;
  617. #endif
  618.         art = curr_art;
  619.                 /* restore to current article */
  620.         return AS_ASK;
  621.     case SRCH_DONE:
  622.         fputs("done\n",stdout) FLUSH;
  623.         pad(just_a_sec/3);    /* 1/3 second */
  624.         if (srchahead)
  625.         art = firstart;
  626.         else
  627.         art = curr_art;
  628.         reread = FALSE;
  629.         return AS_NORM;
  630.     case SRCH_SUBJDONE:
  631. #ifdef UNDEF
  632.         fputs("\n\n\n\nSubject not found.\n",stdout) FLUSH;
  633.         pad(just_a_sec/3);    /* 1/3 second */
  634. #endif
  635.         art = firstart;
  636.         reread = FALSE;
  637.         return AS_NORM;
  638.     case SRCH_NOTFOUND:
  639.         fputs("\n\n\n\nNot found.\n",stdout) FLUSH;
  640.         art = curr_art;  /* restore to current article */
  641.         return AS_ASK;
  642.     case SRCH_FOUND:
  643.         if (cmd == Ctl('n') || cmd == Ctl('p'))
  644.         oldsubject = TRUE;
  645.         break;
  646.     }
  647.     return AS_NORM;
  648.     }
  649. #else
  650.     buf[1] = '\0';
  651.     notincl(buf);
  652.     return AS_ASK;
  653. #endif
  654.     case 'u':            /* unsubscribe from this newsgroup? */
  655.     rcchar[ng] = NEGCHAR;
  656.     return AS_CLEAN;
  657.     case 'M':
  658. #ifdef DELAYMARK
  659.     if (art <= lastart) {
  660.         delay_unmark(art);
  661.         printf("\nArticle %ld will return.\n",(long)art) FLUSH;
  662.     }
  663. #else
  664.     notincl("M");
  665. #endif
  666.     return AS_ASK;
  667.     case 'm':
  668.     if (art <= lastart) {
  669.         unmark_as_read(art);
  670.         printf("\nArticle %ld marked as still unread.\n",(long)art) FLUSH;
  671.     }
  672.     return AS_ASK;
  673.     case 'c':            /* catch up */
  674.       reask_catchup:
  675. #ifdef VERBOSE
  676.     IF(verbose)
  677.         in_char("\nDo you really want to mark everything as read? [yn] ");
  678.     ELSE
  679. #endif
  680. #ifdef TERSE
  681.         in_char("\nReally? [ynh] ");
  682. #endif
  683.     putchar('\n') FLUSH;
  684.     setdef(buf,"y");
  685. #ifdef VERIFY
  686.     printcmd();
  687. #endif
  688.     if (*buf == 'h') {
  689. #ifdef VERBOSE
  690.         IF(verbose)
  691.         fputs("\
  692. Type y or SP to mark all articles as read.\n\
  693. Type n to leave articles marked as they are.\n\
  694. Type u to mark everything read and unsubsubscribe.\n\
  695. ",stdout) FLUSH;
  696.         ELSE
  697. #endif
  698. #ifdef TERSE
  699.         fputs("\
  700. y or SP to mark all read.\n\
  701. n to forget it.\n\
  702. u to mark all and unsubscribe.\n\
  703. ",stdout) FLUSH;
  704. #endif
  705.         goto reask_catchup;
  706.     }
  707.     else if (*buf == 'n' || *buf == 'q') {
  708.         return AS_ASK;
  709.     }
  710.     else if (*buf != 'y' && *buf != 'u') {
  711.         fputs(hforhelp,stdout) FLUSH;
  712.         settle_down();
  713.         goto reask_catchup;
  714.     }
  715.     for (i = firstart; i <= lastart; i++) {
  716.         ctl_set(i);        /* mark as read */
  717.     }
  718. #ifdef DELAYMARK
  719.     if (dmfp)
  720.         yankback();
  721. #endif
  722.     if (*buf == 'u') {
  723.         rcchar[ng] = NEGCHAR;
  724.         return AS_CLEAN;
  725.     }
  726.     art = lastart+1;
  727.     forcelast = FALSE;
  728.     return AS_NORM;
  729.     case 'Q':
  730.     exit_code = NG_ASK;
  731.     /* FALL THROUGH */
  732.     case 'q':            /* go back up to newsgroup level? */
  733.     return AS_CLEAN;
  734.     case 'j':
  735.     putchar('\n') FLUSH;
  736.     if (art <= lastart)
  737.         mark_as_read(art);
  738.     return AS_ASK;
  739.     case 'h': {            /* help? */
  740.     int cmd;
  741.  
  742.     if ((cmd = help_art()) > 0)
  743.         pushchar(cmd);
  744.     return AS_ASK;
  745.     }
  746.     case '&':
  747.     if (switcheroo()) /* get rest of command */
  748.         return AS_INP;    /* if rubbed out, try something else */
  749.     return AS_ASK;
  750.     case '#':
  751. #ifdef VERBOSE
  752.     IF(verbose)
  753.         printf("\nThe last article is %ld.\n",(long)lastart) FLUSH;
  754.     ELSE
  755. #endif
  756. #ifdef TERSE
  757.         printf("\n%ld\n",(long)lastart) FLUSH;
  758. #endif
  759.     return AS_ASK;
  760.     case '=': {
  761.     char tmpbuf[256];
  762.     ART_NUM oldart = art;
  763.     int cmd;
  764.     char *subjline = getval("SUBJLINE",Nullch);
  765. #ifndef CACHESUBJ
  766.     char *s;
  767. #endif
  768.     
  769.     page_init();
  770. #ifdef CACHESUBJ
  771.     if (!subj_list)
  772.         fetchsubj(art,TRUE,FALSE);
  773. #endif
  774.     for (i=firstart; i<=lastart && !int_count; i++) {
  775. #ifdef CACHESUBJ
  776.         if (!was_read(i) &&
  777.           (subj_list[OFFSET(i)] != Nullch || fetchsubj(i,FALSE,FALSE)) &&
  778.           *subj_list[OFFSET(i)] ) {
  779.         sprintf(tmpbuf,"%5ld ", i);
  780.         if (subjline) {
  781.             art = i;
  782.             interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
  783.         }
  784.         else
  785.             safecpy(tmpbuf + 6, subj_list[OFFSET(i)],
  786.             (sizeof tmpbuf) - 6);
  787.         if (cmd = print_lines(tmpbuf,NOMARKING)) {
  788.             if (cmd > 0)
  789.             pushchar(cmd);
  790.             break;
  791.         }
  792.         }
  793. #else
  794.         if (!was_read(i) && (s = fetchsubj(i,FALSE,FALSE)) && *s) {
  795.         sprintf(tmpbuf,"%5ld ", i);
  796.         if (subjline) {    /* probably fetches it again! */
  797.             art = i;
  798.             interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
  799.         }
  800.         else
  801.             safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6);
  802.         if (cmd = print_lines(tmpbuf,NOMARKING)) {
  803.             if (cmd > 0)
  804.             pushchar(cmd);
  805.             break;
  806.         }
  807.         }
  808. #endif
  809.     }
  810.     int_count = 0;
  811.     art = oldart;
  812.     return AS_ASK;
  813.     }
  814.     case '^':
  815.     art = firstart;
  816. #ifdef ARTSEARCH
  817.     srchahead = 0;
  818. #endif
  819.     return AS_NORM;
  820. #if defined(CACHESUBJ) && defined(DEBUGGING)
  821.     case 'D':
  822.     printf("\nFirst article: %ld\n",(long)firstart) FLUSH;
  823.     if (!subj_list)
  824.         fetchsubj(art,TRUE,FALSE);
  825.     if (subj_list != Null(char **)) {
  826.         for (i=1; i<=lastart && !int_count; i++) {
  827.         if (subj_list[OFFSET(i)])
  828.             printf("%5ld %c %s\n",
  829.             i, (was_read(i)?'y':'n'), subj_list[OFFSET(i)]) FLUSH;
  830.         }
  831.     }
  832.     int_count = 0;
  833.     return AS_ASK;
  834. #endif
  835.     case 'v':
  836.     if (art <= lastart) {
  837.         reread = TRUE;
  838.         do_hiding = FALSE;
  839.     }
  840.     return AS_NORM;
  841. #ifdef ROTATION
  842.     case Ctl('x'):
  843. #endif
  844.     case Ctl('r'):
  845. #ifdef ROTATION
  846.     rotate = (*buf==Ctl('x'));
  847. #endif
  848.     if (art <= lastart)
  849.         reread = TRUE;
  850.     return AS_NORM;
  851. #ifdef ROTATION
  852.     case 'X':
  853.     rotate = !rotate;
  854.     /* FALL THROUGH */
  855. #else
  856.     case Ctl('x'):
  857.     case 'x':
  858.     case 'X':
  859.     notincl("x");
  860.     return AS_ASK;
  861. #endif
  862.     case 'l': case Ctl('l'):        /* refresh screen */
  863.     if (art <= lastart) {
  864.         reread = TRUE;
  865.         clear();
  866.         do_fseek = TRUE;
  867.         artline = topline;
  868.         if (artline < 0)
  869.         artline = 0;
  870.     }
  871.     return AS_NORM;
  872.     case 'b': case Ctl('b'):        /* back up a page */
  873.     if (art <= lastart) {
  874.         ART_LINE target;
  875.  
  876.         reread = TRUE;
  877.         clear();
  878.         do_fseek = TRUE;
  879.         target = topline - (LINES - 2);
  880.         artline = topline;
  881.         do {
  882.         artline--;
  883.         } while (artline >= 0 && artline > target &&
  884.         vrdary(artline-1) >= 0);
  885.         topline = artline;
  886.         if (artline < 0)
  887.         artline = 0;
  888.     }
  889.     return AS_NORM;
  890.     case '!':            /* shell escape */
  891.     if (escapade())
  892.         return AS_INP;
  893.     return AS_ASK;
  894.     case 'C': {
  895.     cancel_article();
  896.     return AS_ASK;
  897.     }
  898.     case 'R':
  899.     case 'r': {            /* reply? */
  900.     reply();
  901.     return AS_ASK;
  902.     }
  903.     case 'F':
  904.     case 'f': {            /* followup command */
  905.     followup();
  906.     forcegrow = TRUE;        /* recalculate lastart */
  907.     return AS_ASK;
  908.     }
  909.     case '|':
  910.     case 'w': case 'W':
  911.     case 's': case 'S':        /* save command */
  912.     if (save_article() == SAVE_ABORT)
  913.         return AS_INP;
  914.     return AS_ASK;
  915. #ifdef DELAYMARK
  916.     case 'Y':                /* yank back M articles */
  917.     yankback();
  918.     art = firstart;            /* from the beginning */
  919.     return AS_NORM;            /* pretend nothing happened */
  920. #endif
  921. #ifdef STRICTCR
  922.     case '\n':
  923.     fputs(badcr,stdout) FLUSH;
  924.     return AS_ASK;
  925. #endif
  926.     default:
  927.     printf("\n%s",hforhelp) FLUSH;
  928.     settle_down();
  929.     return AS_ASK;
  930.     }
  931. }
  932.  
  933. #ifdef MAILCALL
  934. /* see if there is any mail */
  935.  
  936. void
  937. setmail()
  938. {
  939.     if (! (mailcount++)) {
  940.     char *mailfile = filexp(getval("MAILFILE",MAILFILE));
  941.     
  942.     if (stat(mailfile,&filestat) < 0 || !filestat.st_size
  943.         || filestat.st_atime > filestat.st_mtime)
  944.         mailcall = nullstr;
  945.     else
  946.         mailcall = "(Mail) ";
  947.     }
  948.     mailcount %= 10;            /* check every 10 articles */
  949. }
  950. #endif
  951.  
  952. void
  953. setdfltcmd()
  954. {
  955.     if (toread[ng]) {
  956. #ifdef ARTSEARCH
  957.     if (srchahead)
  958.         dfltcmd = "^Nnpq";
  959.     else
  960. #endif
  961.         dfltcmd = "npq";
  962.     }
  963.     else {
  964.     if (art > lastart)
  965.         dfltcmd = "qnp";
  966.     else
  967.         dfltcmd = "npq";
  968.     }
  969. }
  970.  
  971. !STUFFY!FUNK!
  972. echo Extracting art.c
  973. cat >art.c <<'!STUFFY!FUNK!'
  974. /* $Header: art.c,v 4.3 85/05/01 11:34:51 lwall Exp $
  975.  *
  976.  * $Log:    art.c,v $
  977.  * Revision 4.3  85/05/01  11:34:51  lwall
  978.  * Baseline for release with 4.3bsd.
  979.  * 
  980.  */
  981.  
  982. #include "EXTERN.h"
  983. #include "common.h"
  984. #include "rn.h"
  985. #include "ngstuff.h"
  986. #include "head.h"
  987. #include "cheat.h"
  988. #include "help.h"
  989. #include "search.h"
  990. #include "artio.h"
  991. #include "ng.h"
  992. #include "bits.h"
  993. #include "final.h"
  994. #include "artstate.h"
  995. #include "rcstuff.h"
  996. #include "term.h"
  997. #include "sw.h"
  998. #include "util.h"
  999. #include "backpage.h"
  1000. #include "intrp.h"
  1001. #include "INTERN.h"
  1002. #include "art.h"
  1003.  
  1004. /* page_switch() return values */
  1005.  
  1006. #define PS_NORM 0
  1007. #define PS_ASK 1
  1008. #define PS_RAISE 2
  1009. #define PS_TOEND 3
  1010.  
  1011. bool special = FALSE;        /* is next page special length? */
  1012. int slines = 0;            /* how long to make page when special */
  1013. ART_LINE highlight = -1;    /* next line to be highlighted */
  1014. char *restart = Nullch;        /* if nonzero, the place where last */
  1015.                 /* line left off on line split */
  1016. char *blinebeg;            /* where in buffer current line began */
  1017. ART_POS alinebeg;        /* where in file current line began */
  1018.  
  1019. #ifdef INNERSEARCH
  1020. ART_POS innersearch = 0;    /* artpos of end of line we found */
  1021.                 /* for 'g' command */
  1022. ART_LINE isrchline = 0;            /* last line to display */
  1023. bool hide_everything = FALSE;
  1024.                 /* if set, do not write page now, */
  1025.                 /* but refresh when done with page */
  1026. COMPEX gcompex;                /* in article search pattern */
  1027. #endif
  1028.  
  1029. bool firstpage;            /* is this the 1st page of article? */
  1030.  
  1031. void
  1032. art_init()
  1033. {
  1034.     ;
  1035. }
  1036.  
  1037. int
  1038. do_article()
  1039. {
  1040.     register char *s;
  1041.     ART_POS artsize;            /* size in bytes of article */
  1042.     char art_buf[LBUFLEN];        /* place for article lines */
  1043.     bool hide_this_line = FALSE;    /* hidden header line? */
  1044.     ART_LINE linenum;    /* line # on page, 1 origin */
  1045. #ifdef ULSMARTS
  1046.     bool under_lining = FALSE;
  1047.                 /* are we underlining a word? */
  1048. #endif
  1049.     register char *bufptr = art_buf;
  1050.                 /* pointer to input buffer */
  1051.     register int outpos;    /* column position of output */
  1052.     static char prompt_buf[64];        /* place to hold prompt */
  1053.     bool notesfiles = FALSE;        /* might there be notesfiles junk? */
  1054.     char oldmode = mode;
  1055.  
  1056. #ifdef INNERSEARCH
  1057.     register int outputok;
  1058. #endif
  1059.  
  1060.     if (fstat(artfp->_file,&filestat))
  1061.                 /* get article file stats */
  1062.     return DA_CLEAN;
  1063.     artsize = filestat.st_size;
  1064.                 /* from that get article size */
  1065.     sprintf(prompt_buf,
  1066.     "%%sEnd of article %ld (of %ld)--what next? [%%s]",
  1067.     (long)art,(long)lastart);    /* format prompt string */
  1068.     prompt = prompt_buf;
  1069.     int_count = 0;        /* interrupt count is 0 */
  1070.     firstpage = (topline < 0);
  1071.     for (;;) {            /* for each page */
  1072.     assert(art == openart);
  1073.     if (do_fseek) {
  1074. #ifdef ASYNC_PARSE
  1075.         parse_maybe(art);        /* make sure header is ours */
  1076. #endif
  1077.         artpos = vrdary(artline);
  1078.         if (artpos < 0)
  1079.         artpos = -artpos;    /* labs(), anyone? */
  1080.         fseek(artfp,artpos,0);
  1081.         if (artpos < htype[PAST_HEADER].ht_minpos)
  1082.         in_header = SOME_LINE;
  1083.         do_fseek = FALSE;
  1084.         restart = Nullch;
  1085.     }
  1086.     if (firstpage) {
  1087.         if (firstline) {
  1088.         interp(art_buf, (sizeof art_buf), firstline);
  1089. #ifdef CLEAREOL
  1090.         maybe_eol();    /* PWP */
  1091. #endif CLEAREOL
  1092.         fputs(art_buf,stdout) FLUSH;
  1093.         artopen(art);        /* rewind article in case interp */
  1094.                     /* forced a header parse */
  1095.         }
  1096.         else {
  1097.         ART_NUM i;
  1098.  
  1099. #ifdef CLEAREOL
  1100.         maybe_eol();    /* PWP */
  1101. #endif CLEAREOL
  1102.         printf("Article %ld",(long)art);
  1103.         i = (((ART_NUM)toread[ng]) - 1 + was_read(art));
  1104. #ifdef DELAYMARK
  1105.         if (i || dmcount) {
  1106.             printf(" (%ld more",(long)i);
  1107.             if (dmcount)
  1108.             printf(" + %ld Marked to return)",(long)dmcount);
  1109.             putchar(')');
  1110.         }
  1111. #else
  1112.         if (i)
  1113.             printf(" (%ld more)",(long)i);
  1114. #endif
  1115.         if (htype[NGS_LINE].ht_flags & HT_HIDE)
  1116.             printf(" in %s", ngname);
  1117.         fputs(":\n",stdout) FLUSH;
  1118.         }
  1119.         start_header(art);
  1120.         forcelast = FALSE;        /* we will have our day in court */
  1121.         restart = Nullch;
  1122.         artline = 0;        /* start counting lines */
  1123.         artpos = 0;
  1124.         vwtary(artline,artpos);    /* remember pos in file */
  1125.     }
  1126.     for (linenum=(firstpage?2:1);
  1127.       in_header || (
  1128. #ifdef INNERSEARCH
  1129.       innersearch ? innermore() :
  1130. #endif
  1131.       linenum<(firstpage?initlines:(special?slines:LINES)) );
  1132.       linenum++) {        /* for each line on page */
  1133.         if (int_count) {    /* exit via interrupt? */
  1134.         putchar('\n') FLUSH;    /* get to left margin */
  1135.         int_count = 0;    /* reset interrupt count */
  1136.         return DA_NORM;    /* skip out of loops */
  1137.         }
  1138.         if (restart) {        /* did not finish last line? */
  1139.         bufptr = restart;    /* then start again here */
  1140.         restart = Nullch;    /* and reset the flag */
  1141.         }
  1142.         else {            /* not a restart */
  1143.         if (fgets(art_buf,LBUFLEN,artfp)==Nullch) {
  1144.                     /* if all done */
  1145.             return DA_NORM;    /* skip out of loops */
  1146.         }
  1147.         bufptr = art_buf;    /* so start at beginning */
  1148.         art_buf[LBUFLEN-1] = '\0';
  1149.                     /* make sure string ends */
  1150.         }
  1151.         blinebeg = bufptr;    /* remember where we began */
  1152.         alinebeg = artpos;    /* both in buffer and file */
  1153.         if (in_header && bufptr == art_buf)
  1154.         hide_this_line =
  1155.             parseline(art_buf,do_hiding,hide_this_line);
  1156.         else if (notesfiles && do_hiding &&
  1157.           bufptr == art_buf && *art_buf == '#' &&
  1158.           isupper(art_buf[1]) && art_buf[2] == ':' ) {
  1159.         fgets(art_buf,sizeof(art_buf),artfp);
  1160.         if (index(art_buf,'!') != Nullch)
  1161.             fgets(art_buf,sizeof(art_buf),artfp);
  1162.         htype[PAST_HEADER].ht_minpos = ftell(artfp);
  1163.                     /* exclude notesfiles droppings */
  1164.         hide_this_line = TRUE;    /* and do not print either */
  1165.         notesfiles = FALSE;
  1166.         }
  1167.         if (in_header && htype[in_header].ht_flags & HT_MAGIC) {
  1168.         if (in_header == NGS_LINE) {
  1169.             hide_this_line = (index(art_buf,',') == Nullch && do_hiding);
  1170.         }
  1171.         else if (in_header == EXPIR_LINE) {
  1172.             if (!(htype[EXPIR_LINE].ht_flags & HT_HIDE))
  1173.             hide_this_line = (strlen(art_buf) < 10 && do_hiding);
  1174.         }
  1175.         }
  1176.         if (in_header == SUBJ_LINE &&
  1177.         htype[SUBJ_LINE].ht_flags & HT_MAGIC) {
  1178.                 /* is this the subject? */
  1179.         int length;
  1180.  
  1181.         length = strlen(art_buf)-1;
  1182.         artline++;
  1183.         art_buf[length] = '\0';        /* wipe out newline */
  1184. #ifdef NOFIREWORKS
  1185.         no_ulfire();
  1186. #endif
  1187.         notesfiles =
  1188.             (instr(&art_buf[length-10]," - (nf") != Nullch);
  1189.         if (oldsubject) {
  1190.             length += 7;
  1191.             fputs("(SAME) ",stdout);
  1192.             oldsubject = FALSE;
  1193.         }
  1194.         if (length+UG > COLS) {        /* rarely true */
  1195.             linenum++;
  1196.             vwtary(artline,vrdary(artline-1)+COLS);
  1197.             artline++;
  1198.         }
  1199.         s = art_buf + 8;
  1200.         *s++ = '\0';    /* make into 2 strings */
  1201. #ifdef CLEAREOL
  1202.         maybe_eol();    /* PWP */
  1203. #endif CLEAREOL
  1204.         fputs(art_buf,stdout) FLUSH;
  1205.                 /* print up through : */
  1206.         if (!UG)
  1207.             putchar(' ');
  1208.         underprint(s);    /* print subject underlined */
  1209.         putchar('\n') FLUSH;    /* and finish the line */
  1210.         }
  1211.         else if (hide_this_line) {    /* do not print line? */
  1212.         linenum--;        /* compensate for linenum++ */
  1213.         if (!in_header)
  1214.             hide_this_line = FALSE;
  1215.         }
  1216.         else {            /* just a normal line */
  1217.         if (highlight==artline) {    /* this line to be highlit? */
  1218.             if (marking == STANDOUT) {
  1219. #ifdef NOFIREWORKS
  1220.             if (erase_screen)
  1221.                 no_sofire();
  1222. #endif
  1223.             standout();
  1224.             }
  1225.             else {
  1226. #ifdef NOFIREWORKS
  1227.             if (erase_screen)
  1228.                 no_ulfire();
  1229. #endif
  1230.             underline();
  1231.             }
  1232.             if (*bufptr == '\n')
  1233.             putchar(' ');
  1234.         }
  1235. #ifdef INNERSEARCH
  1236.         outputok = !hide_everything;
  1237.                     /* get it into register, hopefully */
  1238. #endif
  1239. #ifdef CLEAREOL
  1240. #ifdef INNERSEARCH
  1241.         if (outputok)
  1242. #endif
  1243.         maybe_eol();    /* PWP */
  1244. #endif CLEAREOL
  1245.         for (outpos = 0; outpos < COLS; ) {
  1246.                     /* while line has room */
  1247.             if (*bufptr >= ' ') {    /* normal char? */
  1248. #ifdef ULSMARTS
  1249.             if (*bufptr == '_') {
  1250.                 if (bufptr[1] == '\b') {
  1251.                 if (!under_lining && highlight!=artline
  1252. #ifdef INNERSEARCH
  1253.                     && outputok
  1254. #endif
  1255.                     ) {
  1256.                     under_lining++;
  1257.                     if (UG) {
  1258.                     if (bufptr != buf &&
  1259.                       bufptr[-1] == ' ') {
  1260.                         outpos--;
  1261.                         backspace();
  1262.                     }
  1263.                     }
  1264.                     underline();
  1265.                 }
  1266.                 bufptr += 2;
  1267.                 }
  1268.             }
  1269.             else {
  1270.                 if (under_lining) {
  1271.                 under_lining = 0;
  1272.                 un_underline();
  1273.                 if (UG) {
  1274.                     if (*bufptr == ' ')
  1275.                     goto skip_put;
  1276.                     outpos++;
  1277.                 }
  1278.                 }
  1279.             }
  1280. #endif
  1281. #ifdef INNERSEARCH
  1282.             if (outputok)
  1283. #endif
  1284.             {
  1285. #ifdef ROTATION
  1286.                 if (rotate && !in_header
  1287.                   && isalpha(*bufptr)) {
  1288.                 if ((*bufptr & 31) <= 13)
  1289.                     putchar(*bufptr+13);
  1290.                 else
  1291.                     putchar(*bufptr-13);
  1292.                 }
  1293.                 else
  1294. #endif
  1295.                 putchar(*bufptr);
  1296.             }
  1297.             if (*UC && ((highlight==artline && marking == 1)
  1298. #ifdef ULSMARTS
  1299.                 || under_lining
  1300. #endif
  1301.                 )) {
  1302.                 backspace();
  1303.                 underchar();
  1304.             }
  1305.             skip_put:
  1306.             bufptr++;
  1307.             outpos++;
  1308.             }
  1309.             else if (*bufptr == '\n' || !*bufptr) {
  1310.                             /* newline? */
  1311. #ifdef ULSMARTS
  1312.             if (under_lining) {
  1313.                 under_lining = 0;
  1314.                 un_underline();
  1315.             }
  1316. #endif
  1317. #ifdef DEBUGGING
  1318.             if (debug & DEB_INNERSRCH && outpos < COLS - 6) {
  1319.                 standout();
  1320.                 printf("%4d",artline); 
  1321.                 un_standout();
  1322.             }
  1323. #endif
  1324. #ifdef INNERSEARCH
  1325.             if (outputok)
  1326. #endif
  1327.                 putchar('\n') FLUSH;
  1328.             restart = 0;
  1329.             outpos = 1000;    /* signal normal \n */
  1330.             }
  1331.             else if (*bufptr == '\t') {    /* tab? */
  1332. #ifdef INNERSEARCH
  1333.             if (outputok)
  1334. #endif
  1335.                 putchar(*bufptr);
  1336.             bufptr++;
  1337.             outpos += 8 - outpos % 8;
  1338.             }
  1339.             else if (*bufptr == '\f') {    /* form feed? */
  1340. #ifdef INNERSEARCH
  1341.             if (outputok)
  1342. #endif
  1343.                 fputs("^L",stdout);
  1344.             if (bufptr == blinebeg && highlight != artline)
  1345.                 linenum = 32700;
  1346.                 /* how is that for a magic number? */
  1347.             bufptr++;
  1348.             outpos += 2;
  1349.             }
  1350.             else {        /* other control char */
  1351. #ifdef INNERSEARCH
  1352.             if (outputok)
  1353. #endif
  1354.             {
  1355.                 putchar('^');
  1356.                 if (highlight == artline && *UC && marking == 1) {
  1357.                 backspace();
  1358.                 underchar();
  1359.                 putchar(*bufptr+64);
  1360.                 backspace();
  1361.                 underchar();
  1362.                 }
  1363.                 else
  1364.                 putchar(*bufptr+64);
  1365.             }
  1366.             bufptr++;
  1367.             outpos += 2;
  1368.             }
  1369.             
  1370.         } /* end of column loop */
  1371.  
  1372.         if (outpos < 1000) {/* did line overflow? */
  1373.             restart = bufptr;
  1374.                     /* restart here next time */
  1375.             if (AM) {    /* automatic margins on tty? */
  1376.             if (!XN && *bufptr == '\n')
  1377.                     /* need we simulate XN? */
  1378.                 restart = 0;
  1379.                     /* skip the newline */
  1380.             }
  1381.             else {        /* cursor just hangs there */
  1382. #ifdef INNERSEARCH
  1383.             if (outputok)
  1384. #endif
  1385.                 putchar('\n') FLUSH;
  1386.                     /* so move it down ourselves */
  1387.             if (*bufptr == '\n')
  1388.                 restart = 0;
  1389.                     /* simulate XN if need be */
  1390.             }
  1391. #ifdef CLEAREOL
  1392. /* #ifdef INNERSEARCH
  1393.             if (outputok)
  1394. #endif
  1395.             maybe_eol(); */    /* PWP *//* comment this out for now
  1396.                             until I am sure it is
  1397.                             needed*/
  1398.  
  1399. #endif CLEAREOL
  1400.         }
  1401.  
  1402.         /* handle normal end of output line formalities */
  1403.  
  1404.         if (highlight == artline) {
  1405.                     /* were we highlighting line? */
  1406.             if (marking == STANDOUT)
  1407.             un_standout();
  1408.             else
  1409.             un_underline();
  1410.             highlight = -1;    /* no more we are */
  1411.         }
  1412.         artline++;    /* count the line just printed */
  1413.         if (artline - LINES + 1 > topline)
  1414.                 /* did we just scroll top line off? */
  1415.             topline = artline - LINES + 1;
  1416.                 /* then recompute top line # */
  1417.         }
  1418.  
  1419.         /* determine actual position in file */
  1420.  
  1421.         if (restart)    /* stranded somewhere in the buffer? */
  1422.         artpos += restart - blinebeg;
  1423.                 /* just calculate position */
  1424.         else        /* no, ftell will do */
  1425.         artpos = ftell(artfp);
  1426.                 /* so do ftell */
  1427.         vwtary(artline,artpos);    /* remember pos in file */
  1428.     } /* end of line loop */
  1429.  
  1430. #ifdef INNERSEARCH
  1431.     innersearch = 0;
  1432.     if (hide_everything) {
  1433.         hide_everything = FALSE;
  1434.         *buf = Ctl('l');
  1435.         goto fake_command;
  1436.     }
  1437. #endif
  1438.     if (linenum >= 32700)/* did last line have formfeed? */
  1439.         vwtary(artline-1,-vrdary(artline-1));
  1440.                 /* remember by negating pos in file */
  1441.  
  1442.     special = FALSE;    /* end of page, so reset page length */
  1443.     firstpage = FALSE;    /* and say it is not 1st time thru */
  1444.  
  1445.     /* extra loop bombout */
  1446.  
  1447.     if (artpos == artsize)    /* did we just now reach EOF? */
  1448.         return DA_NORM;    /* avoid --MORE--(100%) */
  1449.  
  1450. /* not done with this article, so pretend we are a pager */
  1451.  
  1452. reask_pager:            
  1453.     unflush_output();    /* disable any ^O in effect */
  1454.     standout();        /* enter standout mode */
  1455.     printf("--MORE--(%ld%%)",(long)(artpos*100/artsize));
  1456.     un_standout();    /* leave standout mode */
  1457.     fflush(stdout);
  1458. /* reinp_pager:                 /* unused, commented for lint */
  1459.     eat_typeahead();
  1460. #ifdef DEBUGGING
  1461.     if (debug & DEB_CHECKPOINTING) {
  1462.         printf("(%d %d %d)",checkcount,linenum,artline);
  1463.         fflush(stdout);
  1464.     }
  1465. #endif
  1466.     if (checkcount >= docheckwhen &&
  1467.       linenum == LINES &&
  1468.       (artline > 40 || checkcount >= docheckwhen+10) ) {
  1469.                 /* while he is reading a whole page */
  1470.                 /* in an article he is interested in */
  1471.         checkcount = 0;
  1472.         checkpoint_rc();    /* update .newsrc */
  1473.     }
  1474.     collect_subjects();        /* loads subject cache until */
  1475.                     /* input is pending */
  1476.     mode = 'p';
  1477.     getcmd(buf);
  1478.     if (errno) {
  1479.         if (LINES < 100 && !int_count)
  1480.         *buf = '\f';/* on CONT fake up refresh */
  1481.         else {
  1482.         *buf = 'q';    /* on INTR or paper just quit */
  1483.         }
  1484.     }
  1485.     carriage_return();
  1486. #ifndef CLEAREOL
  1487.     erase_eol();    /* and erase the prompt */
  1488. #else
  1489.     if (erase_screen && can_home_clear)    /* PWP was here */
  1490.         clear_rest();
  1491.     else
  1492.         erase_eol();    /* and erase the prompt */
  1493. #endif CLEAREOL
  1494.     fflush(stdout);
  1495.  
  1496.     fake_command:        /* used by innersearch */
  1497.  
  1498.     /* parse and process pager command */
  1499.  
  1500.     switch (page_switch()) {
  1501.     case PS_ASK:    /* reprompt "--MORE--..." */
  1502.         goto reask_pager;
  1503.     case PS_RAISE:    /* reparse on article level */
  1504.         mode = oldmode;
  1505.         return DA_RAISE;
  1506.     case PS_TOEND:    /* fast pager loop exit */
  1507.         mode = oldmode;
  1508.         return DA_TOEND;
  1509.     case PS_NORM:    /* display more article */
  1510.         break;
  1511.     }
  1512.     } /* end of page loop */
  1513. }
  1514.  
  1515. /* process pager commands */
  1516.  
  1517. int
  1518. page_switch()
  1519. {
  1520.     register char *s;
  1521.     
  1522.     switch (*buf) {
  1523.     case 'd':
  1524.     case Ctl('d'):    /* half page */
  1525.     special = TRUE;
  1526.     slines = LINES / 2 + 1;
  1527.     if (marking && *blinebeg != '\f') {
  1528.         up_line();
  1529.         highlight = --artline;
  1530.         restart = blinebeg;
  1531.         artpos = alinebeg;
  1532.     }
  1533.     return PS_NORM;
  1534.     case '!':            /* shell escape */
  1535.     escapade();
  1536.     return PS_ASK;
  1537. #ifdef INNERSEARCH
  1538.     case Ctl('i'):
  1539.     gline = 3;
  1540.     sprintf(cmd_buf,"^[^%c]",*blinebeg);
  1541.     compile(&gcompex,cmd_buf,TRUE,TRUE);
  1542.     goto caseG;
  1543.     case Ctl('g'):
  1544.     gline = 3;
  1545.     compile(&gcompex,"^Subject:",TRUE,TRUE);
  1546.     goto caseG;
  1547.     case 'g':        /* in-article search */
  1548.     if (!finish_command(FALSE))/* get rest of command */
  1549.         return PS_ASK;
  1550.     s = buf+1;
  1551.     if (isspace(*s))
  1552.         s++;
  1553.     if ((s = compile(&gcompex,s,TRUE,TRUE)) != Nullch) {
  1554.                 /* compile regular expression */
  1555.         printf("\n%s\n",s) FLUSH;
  1556.         return PS_ASK;
  1557.     }
  1558.     carriage_return();
  1559.     erase_eol();    /* erase the prompt */
  1560.     /* FALL THROUGH */
  1561.     caseG:
  1562.     case 'G': {
  1563.     /* ART_LINE lines_to_skip = 0; */
  1564.     ART_POS start_where;
  1565.  
  1566.     if (gline < 0 || gline > LINES-2)
  1567.         gline = LINES-2;
  1568. #ifdef DEBUGGING
  1569.     if (debug & DEB_INNERSRCH)
  1570.         printf("Start here? %d  >=? %d\n",topline + gline + 1,artline)
  1571.           FLUSH;
  1572. #endif
  1573.     if (*buf == Ctl('i') || topline+gline+1 >= artline)
  1574.         start_where = artpos;
  1575.             /* in case we had a line wrap */
  1576.     else {
  1577.         start_where = vrdary(topline+gline+1);
  1578.         if (start_where < 0)
  1579.         start_where = -start_where;
  1580.     }
  1581.     if (start_where < htype[PAST_HEADER].ht_minpos)
  1582.         start_where = htype[PAST_HEADER].ht_minpos;
  1583.     fseek(artfp,(long)start_where,0);
  1584.     innersearch = 0; /* assume not found */
  1585.     while (fgets(buf, sizeof buf, artfp) != Nullch) {
  1586.         /* lines_to_skip++;         NOT USED NOW */
  1587. #ifdef DEBUGGING
  1588.         if (debug & DEB_INNERSRCH)
  1589.         printf("Test %s",buf) FLUSH;
  1590. #endif
  1591.         if (execute(&gcompex,buf) != Nullch) {
  1592.         innersearch = ftell(artfp);
  1593.         break;
  1594.         }
  1595.     }
  1596.     if (!innersearch) {
  1597.         fseek(artfp,artpos,0);
  1598.         fputs("(Not found)",stdout) FLUSH;
  1599.         return PS_ASK;
  1600.     }
  1601. #ifdef DEBUGGING
  1602.     if (debug & DEB_INNERSRCH)
  1603.         printf("On page? %ld <=? %ld\n",(long)innersearch,(long)artpos)
  1604.           FLUSH;
  1605. #endif
  1606.     if (innersearch <= artpos) {    /* already on page? */
  1607.         if (innersearch < artpos) {
  1608.         artline = topline+1;
  1609.         while (vrdary(artline) < innersearch)
  1610.             artline++;
  1611.         }
  1612.         highlight = artline - 1;
  1613. #ifdef DEBUGGING
  1614.         if (debug & DEB_INNERSRCH)
  1615.         printf("@ %d\n",highlight) FLUSH;
  1616. #endif
  1617.         topline = highlight - gline;
  1618.         if (topline < -1)
  1619.         topline = -1;
  1620.         *buf = '\f';        /* fake up a refresh */
  1621.         innersearch = 0;
  1622.         return page_switch();
  1623.     }
  1624.     else {                /* who knows how many lines it is? */
  1625.         do_fseek = TRUE;
  1626.         hide_everything = TRUE;
  1627.     }
  1628.     return PS_NORM;
  1629.     }
  1630. #else
  1631.     case 'g': case 'G': case Ctl('g'):
  1632.     notincl("g");
  1633.     return PS_ASK;
  1634. #endif
  1635.     case '\n':        /* one line */
  1636.     special = TRUE;
  1637.     slines = 2;
  1638.     return PS_NORM;
  1639. #ifdef ROTATION
  1640.     case 'X':
  1641.     rotate = !rotate;
  1642.     /* FALL THROUGH */
  1643. #endif
  1644.     case 'l':
  1645.     case '\f':        /* refresh screen */
  1646. #ifdef DEBUGGING
  1647.     if (debug & DEB_INNERSRCH) {
  1648.         printf("Topline = %d",topline) FLUSH;
  1649.         gets(buf);
  1650.     }
  1651. #endif
  1652.     clear();
  1653.     do_fseek = TRUE;
  1654.     artline = topline;
  1655.     if (artline < 0)
  1656.         artline = 0;
  1657.     firstpage = (topline < 0);
  1658.     return PS_NORM;
  1659.     case 'b':
  1660.     case '\b':            /* I like backspace for this -- PWP */
  1661.                     /* Leaving it undocumented in case */
  1662.                     /* I want to steal the key--LAW */
  1663.     case Ctl('b'): {    /* back up a page */
  1664.     ART_LINE target;
  1665.  
  1666. #ifndef CLEAREOL
  1667.     clear();
  1668. #else
  1669.     if (can_home_clear)    /* if we can home do it -- PWP */
  1670.         home_cursor();
  1671.     else
  1672.         clear();
  1673.  
  1674. #endif CLEAREOL
  1675.     do_fseek = TRUE;    /* reposition article file */
  1676.     target = topline - (LINES - 2);
  1677.     artline = topline;
  1678.     do {
  1679.         artline--;
  1680.     } while (artline >= 0 && artline > target &&
  1681.         vrdary(artline-1) >= 0);
  1682.     topline = artline;
  1683.             /* remember top line of screen */
  1684.             /*  (line # within article file) */
  1685.     if (artline < 0)
  1686.         artline = 0;
  1687.     firstpage = (topline < 0);
  1688.     return PS_NORM;
  1689.     }
  1690.     case 'h': {        /* help */
  1691.     int cmd;
  1692.  
  1693.     if ((cmd = help_page()) > 0)
  1694.         pushchar(cmd);
  1695.     return PS_ASK;
  1696.     }
  1697.     case '\177':
  1698.     case '\0':        /* treat del,break as 'n' */
  1699.     *buf = 'n';
  1700.     /* FALL THROUGH */
  1701.     case 'k':    case 'K':
  1702.     case 'n':    case 'N':    case Ctl('n'):
  1703.     case 's':    case 'S':
  1704.     case 'u':
  1705.     case 'w':    case 'W':
  1706.     case '|':
  1707.     mark_as_read(art);    /* mark article as read */
  1708.     /* FALL THROUGH */
  1709.     case '#':
  1710.     case '$':
  1711.     case '&':
  1712.     case '-':
  1713.     case '.':
  1714.     case '/':
  1715.     case '1': case '2': case '3': case '4': case '5':
  1716.     case '6': case '7': case '8': case '9':
  1717.     case '=':
  1718.     case '?':
  1719.     case 'c':    case 'C':    
  1720.     case 'f':    case 'F':    
  1721.     case 'j':
  1722.                 case Ctl('k'):
  1723.     case 'm':    case 'M':    
  1724.     case 'p':    case 'P':    case Ctl('p'):    
  1725.         case 'Q':
  1726.     case 'r':    case 'R':    case Ctl('r'):
  1727.     case 'v':
  1728.         case 'Y':
  1729. #ifndef ROTATION
  1730.     case 'x':    case 'X':
  1731. #endif
  1732.     case Ctl('x'):
  1733.     case '^':
  1734.  
  1735. #ifdef ROTATION
  1736.     rotate = FALSE;
  1737. #endif
  1738.     reread = FALSE;
  1739.     do_hiding = TRUE;
  1740.     if (index("nNpP",*buf) == Nullch &&
  1741.       index("wWsS!&|/?123456789.",*buf) != Nullch) {
  1742.         setdfltcmd();
  1743.         standout();        /* enter standout mode */
  1744.         printf(prompt,mailcall,dfltcmd);
  1745.                 /* print prompt, whatever it is */
  1746.         un_standout();    /* leave standout mode */
  1747.         putchar(' ');
  1748.         fflush(stdout);
  1749.     }
  1750.     return PS_RAISE;    /* and pretend we were at end */
  1751. #ifdef ROTATION
  1752.     case 'x':
  1753.     rotate = TRUE;
  1754.     /* FALL THROUGH */
  1755. #endif
  1756.     case 'y':
  1757.     case Ctl('v'):        /* I like emacs -- PWP */
  1758.                     /* Leaving it undocumented in case */
  1759.                     /* I want to steal the key--LAW */
  1760.     case ' ':    /* continue current article */
  1761.     if (erase_screen) {    /* -e? */
  1762. #ifndef CLEAREOL
  1763.         clear();        /* clear screen */
  1764. #else
  1765.         if (can_home_clear)    /* if we can home do it -- PWP */
  1766.         home_cursor();
  1767.         else
  1768.         clear();    /* else clear screen */
  1769.  
  1770. #endif CLEAREOL
  1771.         if (*blinebeg != '\f') {
  1772.         restart = blinebeg;
  1773.         artline--;     /* restart this line */
  1774.         artpos = alinebeg;
  1775.         if (marking)    /* and mark repeated line */
  1776.             highlight = artline;
  1777.         }
  1778.         topline = artline;
  1779.             /* and remember top line of screen */
  1780.             /*  (line # within article file) */
  1781.     }
  1782.     else if (marking && *blinebeg != '\f') {
  1783.                 /* are we marking repeats? */
  1784.         up_line();        /* go up one line */
  1785.         highlight = --artline;/* and get ready to highlight */
  1786.         restart = blinebeg;    /*   the old line */
  1787.         artpos = alinebeg;
  1788.     }
  1789.     return PS_NORM;
  1790.     case 'q':    /* quit this article? */
  1791.     do_hiding = TRUE;
  1792.     return PS_TOEND;
  1793.     default:
  1794.     fputs(hforhelp,stdout) FLUSH;
  1795.     settle_down();
  1796.     return PS_ASK;
  1797.     }
  1798. }
  1799.  
  1800. #ifdef INNERSEARCH
  1801. bool
  1802. innermore()
  1803. {
  1804.     if (artpos < innersearch) {        /* not even on page yet? */
  1805. #ifdef DEBUGGING
  1806.     if (debug & DEB_INNERSRCH)
  1807.         printf("Not on page %ld < %ld\n",(long)artpos,(long)innersearch)
  1808.           FLUSH;
  1809. #endif
  1810.     return TRUE;
  1811.     }
  1812.     if (artpos == innersearch) {    /* just got onto page? */
  1813.     isrchline = artline;        /* remember first line after */
  1814.     highlight = artline - 1;
  1815. #ifdef DEBUGGING
  1816.     if (debug & DEB_INNERSRCH)
  1817.         printf("There it is %ld = %ld, %d @ %d\n",(long)artpos,
  1818.         (long)innersearch,hide_everything,highlight) FLUSH;
  1819. #endif
  1820.     if (hide_everything) {        /* forced refresh? */
  1821.         topline = highlight - gline;
  1822.         if (topline < -1)
  1823.         topline = -1;
  1824.         return FALSE;        /* let refresh do it all */
  1825.     }
  1826.     }
  1827. #ifdef DEBUGGING
  1828.     if (debug & DEB_INNERSRCH)
  1829.     printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline)
  1830.       FLUSH;
  1831. #endif
  1832.     if (artline < isrchline + gline) {
  1833.     return TRUE;
  1834.     }
  1835.     return FALSE;
  1836. }
  1837. #endif
  1838. !STUFFY!FUNK!
  1839. echo Extracting search.c
  1840. cat >search.c <<'!STUFFY!FUNK!'
  1841. /* $Header: search.c,v 4.3 85/05/01 11:50:16 lwall Exp $
  1842.  *
  1843.  * $Log:    search.c,v $
  1844.  * Revision 4.3  85/05/01  11:50:16  lwall
  1845.  * Baseline for release with 4.3bsd.
  1846.  * 
  1847.  */
  1848.  
  1849. /* string search routines */
  1850.  
  1851. /*        Copyright (c) 1981,1980 James Gosling        */
  1852.  
  1853. /* Modified Aug. 12, 1981 by Tom London to include regular expressions
  1854.    as in ed.  RE stuff hacked over by jag to correct a few major problems,
  1855.    mainly dealing with searching within the buffer rather than copying
  1856.    each line to a separate array.  Newlines can now appear in RE's */
  1857.  
  1858. /* Ripped to shreds and glued back together to make a search package,
  1859.  * July 6, 1984, by Larry Wall. (If it doesn't work, it's probably my fault.)
  1860.  * Changes include:
  1861.  *    Buffer, window, and mlisp stuff gone.
  1862.  *    Translation tables reduced to 1 table.
  1863.  *    Expression buffer is now dynamically allocated.
  1864.  *    Character classes now implemented with a bitmap.
  1865.  */
  1866.  
  1867. #include "EXTERN.h"
  1868. #include "common.h"
  1869. #include "util.h"
  1870. #include "INTERN.h"
  1871. #include "search.h"
  1872.  
  1873. #ifndef BITSPERBYTE
  1874. #define BITSPERBYTE 8
  1875. #endif
  1876.  
  1877. #define BMAPSIZ (127 / BITSPERBYTE + 1)
  1878.  
  1879. /* meta characters in the "compiled" form of a regular expression */
  1880. #define    CBRA    2        /* \( -- begin bracket */
  1881. #define    CCHR    4        /* a vanilla character */
  1882. #define    CDOT    6        /* . -- match anything except a newline */
  1883. #define    CCL    8        /* [...] -- character class */
  1884. #define    NCCL    10        /* [^...] -- negated character class */
  1885. #define    CDOL    12        /* $ -- matches the end of a line */
  1886. #define    CEND    14        /* The end of the pattern */
  1887. #define    CKET    16        /* \) -- close bracket */
  1888. #define    CBACK    18        /* \N -- backreference to the Nth bracketed
  1889.                    string */
  1890. #define CIRC    20        /* ^ matches the beginning of a line */
  1891.  
  1892. #define WORD    32        /* matches word character \w */
  1893. #define NWORD    34        /* matches non-word characer \W */
  1894. #define WBOUND    36        /* matches word boundary \b */
  1895. #define NWBOUND    38        /* matches non-(word boundary) \B */
  1896.  
  1897. #define    STAR    01        /* * -- Kleene star, repeats the previous
  1898.                    REas many times as possible; the value
  1899.                    ORs with the other operator types */
  1900.  
  1901. #define ASCSIZ 0200
  1902. typedef char    TRANSTABLE[ASCSIZ];
  1903.  
  1904. static    TRANSTABLE trans = {
  1905. 0000,0001,0002,0003,0004,0005,0006,0007,
  1906. 0010,0011,0012,0013,0014,0015,0016,0017,
  1907. 0020,0021,0022,0023,0024,0025,0026,0027,
  1908. 0030,0031,0032,0033,0034,0035,0036,0037,
  1909. 0040,0041,0042,0043,0044,0045,0046,0047,
  1910. 0050,0051,0052,0053,0054,0055,0056,0057,
  1911. 0060,0061,0062,0063,0064,0065,0066,0067,
  1912. 0070,0071,0072,0073,0074,0075,0076,0077,
  1913. 0100,0101,0102,0103,0104,0105,0106,0107,
  1914. 0110,0111,0112,0113,0114,0115,0116,0117,
  1915. 0120,0121,0122,0123,0124,0125,0126,0127,
  1916. 0130,0131,0132,0133,0134,0135,0136,0137,
  1917. 0140,0141,0142,0143,0144,0145,0146,0147,
  1918. 0150,0151,0152,0153,0154,0155,0156,0157,
  1919. 0160,0161,0162,0163,0164,0165,0166,0167,
  1920. 0170,0171,0172,0173,0174,0175,0176,0177,
  1921. };
  1922. static bool folding = FALSE;
  1923.  
  1924. static int err;
  1925. static char *FirstCharacter;
  1926.  
  1927. void
  1928. search_init()
  1929. {
  1930. #ifdef UNDEF
  1931.     register int    i;
  1932.     
  1933.     for (i = 0; i < ASCSIZ; i++)
  1934.     trans[i] = i;
  1935. #else
  1936.     ;
  1937. #endif
  1938. }
  1939.  
  1940. void
  1941. init_compex(compex)
  1942. register COMPEX *compex;
  1943. {
  1944.     /* the following must start off zeroed */
  1945.  
  1946.     compex->eblen = 0;
  1947.     compex->brastr = Nullch;
  1948. }
  1949.  
  1950. void
  1951. free_compex(compex)
  1952. register COMPEX *compex;
  1953. {
  1954.     if (compex->eblen) {
  1955.     free(compex->expbuf);
  1956.     compex->eblen = 0;
  1957.     }
  1958.     if (compex->brastr) {
  1959.     free(compex->brastr);
  1960.     compex->brastr = Nullch;
  1961.     }
  1962. }
  1963.  
  1964. static char *gbr_str = Nullch;
  1965. static int gbr_siz = 0;
  1966.  
  1967. char *
  1968. getbracket(compex,n)
  1969. register COMPEX *compex;
  1970. int n;
  1971. {
  1972.     int length = compex->braelist[n] - compex->braslist[n];
  1973.  
  1974.     if (!compex->nbra || n > compex->nbra || !compex->braelist[n] || length<0)
  1975.     return nullstr;
  1976.     growstr(&gbr_str, &gbr_siz, length+1);
  1977.     safecpy(gbr_str, compex->braslist[n], length+1);
  1978.     return gbr_str;
  1979. }
  1980.  
  1981. void
  1982. case_fold(which)
  1983. int which;
  1984. {
  1985.     register int i;
  1986.  
  1987.     if (which != folding) {
  1988.     if (which) {
  1989.         for (i = 'A'; i <= 'Z'; i++)
  1990.         trans[i] = tolower(i);
  1991.     }
  1992.     else {
  1993.         for (i = 'A'; i <= 'Z'; i++)
  1994.         trans[i] = i;
  1995.     }
  1996.     folding = which;
  1997.     }
  1998. }
  1999.  
  2000. /* Compile the given regular expression into a [secret] internal format */
  2001.  
  2002. char *
  2003. compile (compex, strp, RE, fold)
  2004. register COMPEX *compex;
  2005. register char   *strp;
  2006. int RE;
  2007. int fold;
  2008. {
  2009.     register int c;
  2010.     register char  *ep;
  2011.     char   *lastep;
  2012.     char    bracket[NBRA],
  2013.        *bracketp;
  2014.     char **alt = compex->alternatives;
  2015.     char *retmes = "Badly formed search string";
  2016.  
  2017.     case_fold(compex->do_folding = fold);
  2018.     if (!compex->eblen) {
  2019.     compex->expbuf = safemalloc(84);
  2020.     compex->eblen = 80;
  2021.     }
  2022.     ep = compex->expbuf;        /* point at expression buffer */
  2023.     *alt++ = ep;            /* first alternative starts here */
  2024.     bracketp = bracket;            /* first bracket goes here */
  2025.     if (*strp == 0) {            /* nothing to compile? */
  2026.     if (*ep == 0)            /* nothing there yet? */
  2027.         return "Null search string";
  2028.     return Nullch;            /* just keep old expression */
  2029.     }
  2030.     compex->nbra = 0;            /* no brackets yet */
  2031.     lastep = 0;
  2032.     for (;;) {
  2033.     if (ep - compex->expbuf >= compex->eblen)
  2034.         grow_eb(compex);
  2035.     c = *strp++;            /* fetch next char of pattern */
  2036.     if (c == 0) {            /* end of pattern? */
  2037.         if (bracketp != bracket) {    /* balanced brackets? */
  2038. #ifdef VERBOSE
  2039.         retmes = "Unbalanced parens";
  2040. #endif
  2041.         goto cerror;
  2042.         }
  2043.         *ep++ = CEND;        /* terminate expression */
  2044.         *alt++ = 0;            /* terminal alternative list */
  2045.         /*
  2046.         compex->eblen = ep - compex->expbuf + 1;
  2047.         compex->expbuf = saferealloc(compex->expbuf,compex->eblen+4); */
  2048.         return Nullch;        /* return success */
  2049.     }
  2050.     if (c != '*')
  2051.         lastep = ep;
  2052.     if (!RE) {            /* just a normal search string? */
  2053.         *ep++ = CCHR;        /* everything is a normal char */
  2054.         *ep++ = c;
  2055.     }
  2056.     else                /* it is a regular expression */
  2057.         switch (c) {
  2058.  
  2059.         case '\\':        /* meta something */
  2060.             switch (c = *strp++) {
  2061.             case '(':
  2062.             if (compex->nbra >= NBRA) {
  2063. #ifdef VERBOSE
  2064.                 retmes = "Too many parens";
  2065. #endif
  2066.                 goto cerror;
  2067.             }
  2068.             *bracketp++ = ++compex->nbra;
  2069.             *ep++ = CBRA;
  2070.             *ep++ = compex->nbra;
  2071.             break;
  2072.             case '|':
  2073.             if (bracketp>bracket) {
  2074. #ifdef VERBOSE
  2075.                 retmes = "No \\| in parens";    /* Alas! */
  2076. #endif
  2077.                 goto cerror;
  2078.             }
  2079.             *ep++ = CEND;
  2080.             *alt++ = ep;
  2081.             break;
  2082.             case ')':
  2083.             if (bracketp <= bracket) {
  2084. #ifdef VERBOSE
  2085.                 retmes = "Unmatched right paren";
  2086. #endif
  2087.                 goto cerror;
  2088.             }
  2089.             *ep++ = CKET;
  2090.             *ep++ = *--bracketp;
  2091.             break;
  2092.             case 'w':
  2093.             *ep++ = WORD;
  2094.             break;
  2095.             case 'W':
  2096.             *ep++ = NWORD;
  2097.             break;
  2098.             case 'b':
  2099.             *ep++ = WBOUND;
  2100.             break;
  2101.             case 'B':
  2102.             *ep++ = NWBOUND;
  2103.             break;
  2104.             case '0': case '1': case '2': case '3': case '4':
  2105.             case '5': case '6': case '7': case '8': case '9':
  2106.             *ep++ = CBACK;
  2107.             *ep++ = c - '0';
  2108.             break;
  2109.             default:
  2110.             *ep++ = CCHR;
  2111.             if (c == '\0')
  2112.                 goto cerror;
  2113.             *ep++ = c;
  2114.             break;
  2115.             }
  2116.             break;
  2117.         case '.':
  2118.             *ep++ = CDOT;
  2119.             continue;
  2120.  
  2121.         case '*':
  2122.             if (lastep == 0 || *lastep == CBRA || *lastep == CKET
  2123.             || *lastep == CIRC
  2124.             || (*lastep&STAR)|| *lastep>NWORD)
  2125.             goto defchar;
  2126.             *lastep |= STAR;
  2127.             continue;
  2128.  
  2129.         case '^':
  2130.             if (ep != compex->expbuf && ep[-1] != CEND)
  2131.             goto defchar;
  2132.             *ep++ = CIRC;
  2133.             continue;
  2134.  
  2135.         case '$':
  2136.             if (*strp != 0 && (*strp != '\\' || strp[1] != '|'))
  2137.             goto defchar;
  2138.             *ep++ = CDOL;
  2139.             continue;
  2140.  
  2141.         case '[': {        /* character class */
  2142.             register int i;
  2143.             
  2144.             if (ep - compex->expbuf >= compex->eblen - BMAPSIZ)
  2145.             grow_eb(compex);    /* reserve bitmap */
  2146.             for (i = BMAPSIZ; i; --i)
  2147.             ep[i] = 0;
  2148.             
  2149.             if ((c = *strp++) == '^') {
  2150.             c = *strp++;
  2151.             *ep++ = NCCL;    /* negated */
  2152.             }
  2153.             else
  2154.             *ep++ = CCL;    /* normal */
  2155.             
  2156.             i = 0;        /* remember oldchar */
  2157.             do {
  2158.             if (c == '\0') {
  2159. #ifdef VERBOSE
  2160.                 retmes = "Missing ]";
  2161. #endif
  2162.                 goto cerror;
  2163.             }
  2164.             if (*strp == '-' && *(++strp))
  2165.                 i = *strp++;
  2166.             else
  2167.                 i = c;
  2168.             while (c <= i) {
  2169.                 ep[c / BITSPERBYTE] |= 1 << (c % BITSPERBYTE);
  2170.                 if (fold && isalpha(c))
  2171.                 ep[(c ^ 32) / BITSPERBYTE] |=
  2172.                     1 << ((c ^ 32) % BITSPERBYTE);
  2173.                     /* set the other bit too */
  2174.                 c++;
  2175.             }
  2176.             } while ((c = *strp++) != ']');
  2177.             ep += BMAPSIZ;
  2178.             continue;
  2179.         }
  2180.  
  2181.         defchar:
  2182.         default:
  2183.             *ep++ = CCHR;
  2184.             *ep++ = c;
  2185.         }
  2186.     }
  2187. cerror:
  2188.     compex->expbuf[0] = 0;
  2189.     compex->nbra = 0;
  2190.     return retmes;
  2191. }
  2192.  
  2193. void
  2194. grow_eb(compex)
  2195. register COMPEX *compex;
  2196. {
  2197.     compex->eblen += 80;
  2198.     compex->expbuf = saferealloc(compex->expbuf, (MEM_SIZE)compex->eblen + 4);
  2199. }
  2200.  
  2201. char *
  2202. execute (compex, addr)
  2203. register COMPEX *compex;
  2204. char *addr;
  2205. {
  2206.     register char *p1 = addr;
  2207.     register char *trt = trans;
  2208.     register int c;
  2209.  
  2210.     if (addr == Nullch)
  2211.     return Nullch;
  2212.     if (compex->nbra) {            /* any brackets? */
  2213.     for (c = 0; c <= compex->nbra; c++)
  2214.         compex->braslist[c] = compex->braelist[c] = Nullch;
  2215.     if (compex->brastr)
  2216.         free(compex->brastr);
  2217.     compex->brastr = savestr(p1);    /* in case p1 is not static */
  2218.     p1 = compex->brastr;        /* ! */
  2219.     }
  2220.     case_fold(compex->do_folding);    /* make sure table is correct */
  2221.     FirstCharacter = p1;        /* for ^ tests */
  2222.     if (compex->expbuf[0] == CCHR && !compex->alternatives[1]) {
  2223.     c = trt[compex->expbuf[1]];    /* fast check for first character */
  2224.     do {
  2225.         if (trt[*p1] == c && advance (compex, p1, compex->expbuf))
  2226.         return p1;
  2227.         p1++;
  2228.     } while (*p1 && !err);
  2229.     return Nullch;
  2230.     }
  2231.     else {            /* regular algorithm */
  2232.     do {
  2233.         register char **alt = compex->alternatives;
  2234.         while (*alt) {
  2235.         if (advance (compex, p1, *alt++))
  2236.             return p1;
  2237.         }
  2238.         p1++;
  2239.     } while (*p1 && !err);
  2240.     return Nullch;
  2241.     }
  2242. }
  2243.  
  2244. /* advance the match of the regular expression starting at ep along the
  2245.    string lp, simulates an NDFSA */
  2246. bool
  2247. advance (compex, lp, ep)
  2248. register COMPEX *compex;
  2249. register char *ep;
  2250. register char *lp;
  2251. {
  2252.     register char *curlp;
  2253.     register char *trt = trans;
  2254.     register int i;
  2255.  
  2256.     while ((*ep & STAR) || *lp || *ep == CIRC || *ep == CKET)
  2257.     switch (*ep++) {
  2258.  
  2259.         case CCHR:
  2260.         if (trt[*ep++] != trt[*lp]) return FALSE;
  2261.         lp++;
  2262.         continue;
  2263.  
  2264.         case CDOT:
  2265.         if (*lp == '\n') return FALSE;
  2266.         lp++;
  2267.         continue;
  2268.  
  2269.         case CDOL:
  2270.         if (!*lp || *lp == '\n')
  2271.             continue;
  2272.         return FALSE;
  2273.  
  2274.         case CIRC:
  2275.         if (lp == FirstCharacter || lp[-1]=='\n')
  2276.             continue;
  2277.         return FALSE;
  2278.  
  2279.         case WORD:
  2280.         if (isalnum(*lp)) {
  2281.             lp++;
  2282.             continue;
  2283.         }
  2284.         return FALSE;
  2285.  
  2286.         case NWORD:
  2287.         if (!isalnum(*lp)) {
  2288.             lp++;
  2289.             continue;
  2290.         }
  2291.         return FALSE;
  2292.  
  2293.         case WBOUND:
  2294.         if ((lp == FirstCharacter || !isalnum(lp[-1])) !=
  2295.             (!*lp || !isalnum(*lp)) )
  2296.             continue;
  2297.         return FALSE;
  2298.  
  2299.         case NWBOUND:
  2300.         if ((lp == FirstCharacter || !isalnum(lp[-1])) ==
  2301.             (!*lp || !isalnum(*lp)))
  2302.             continue;
  2303.         return FALSE;
  2304.  
  2305.         case CEND:
  2306.         return TRUE;
  2307.  
  2308.         case CCL:
  2309.         if (cclass (ep, *lp, 1)) {
  2310.             ep += BMAPSIZ;
  2311.             lp++;
  2312.             continue;
  2313.         }
  2314.         return FALSE;
  2315.  
  2316.         case NCCL:
  2317.         if (cclass (ep, *lp, 0)) {
  2318.             ep += BMAPSIZ;
  2319.             lp++;
  2320.             continue;
  2321.         }
  2322.         return FALSE;
  2323.  
  2324.         case CBRA:
  2325.         compex->braslist[*ep++] = lp;
  2326.         continue;
  2327.  
  2328.         case CKET:
  2329.         i = *ep++;
  2330.         compex->braelist[i] = lp;
  2331.         compex->braelist[0] = lp;
  2332.         compex->braslist[0] = compex->braslist[i];
  2333.         continue;
  2334.  
  2335.         case CBACK:
  2336.         if (compex->braelist[i = *ep++] == 0) {
  2337.             fputs("bad braces\n",stdout) FLUSH;
  2338.             err = TRUE;
  2339.             return FALSE;
  2340.         }
  2341.         if (backref (compex, i, lp)) {
  2342.             lp += compex->braelist[i] - compex->braslist[i];
  2343.             continue;
  2344.         }
  2345.         return FALSE;
  2346.  
  2347.         case CBACK | STAR:
  2348.         if (compex->braelist[i = *ep++] == 0) {
  2349.             fputs("bad braces\n",stdout) FLUSH;
  2350.             err = TRUE;
  2351.             return FALSE;
  2352.         }
  2353.         curlp = lp;
  2354.         while (backref (compex, i, lp)) {
  2355.             lp += compex->braelist[i] - compex->braslist[i];
  2356.         }
  2357.         while (lp >= curlp) {
  2358.             if (advance (compex, lp, ep))
  2359.             return TRUE;
  2360.             lp -= compex->braelist[i] - compex->braslist[i];
  2361.         }
  2362.         continue;
  2363.  
  2364.         case CDOT | STAR:
  2365.         curlp = lp;
  2366.         while (*lp++ && lp[-1] != '\n');
  2367.         goto star;
  2368.  
  2369.         case WORD | STAR:
  2370.         curlp = lp;
  2371.         while (*lp++ && isalnum(lp[-1]));
  2372.         goto star;
  2373.  
  2374.         case NWORD | STAR:
  2375.         curlp = lp;
  2376.         while (*lp++ && !isalnum(lp[-1]));
  2377.         goto star;
  2378.  
  2379.         case CCHR | STAR:
  2380.         curlp = lp;
  2381.         while (*lp++ && trt[lp[-1]] == trt[*ep]);
  2382.         ep++;
  2383.         goto star;
  2384.  
  2385.         case CCL | STAR:
  2386.         case NCCL | STAR:
  2387.         curlp = lp;
  2388.         while (*lp++ && cclass (ep, lp[-1], ep[-1] == (CCL | STAR)));
  2389.         ep += BMAPSIZ;
  2390.         goto star;
  2391.  
  2392.     star:
  2393.         do {
  2394.             lp--;
  2395.             if (advance (compex, lp, ep))
  2396.             return TRUE;
  2397.         } while (lp > curlp);
  2398.         return FALSE;
  2399.  
  2400.         default:
  2401.         fputs("Badly compiled pattern\n",stdout) FLUSH;
  2402.         err = TRUE;
  2403.         return -1;
  2404.     }
  2405.     if (*ep == CEND || *ep == CDOL) {
  2406.         return TRUE;
  2407.     }
  2408.     return FALSE;
  2409. }
  2410.  
  2411. bool
  2412. backref (compex, i, lp)
  2413. register COMPEX *compex;
  2414. register int i;
  2415. register char *lp;
  2416. {
  2417.     register char *bp;
  2418.  
  2419.     bp = compex->braslist[i];
  2420.     while (*lp && *bp == *lp) {
  2421.     bp++;
  2422.     lp++;
  2423.     if (bp >= compex->braelist[i])
  2424.         return TRUE;
  2425.     }
  2426.     return FALSE;
  2427. }
  2428.  
  2429. bool
  2430. cclass (set, c, af)
  2431. register char  *set;
  2432. register int c;
  2433. {
  2434.     c &= 0177;
  2435. #if BITSPERBYTE == 8
  2436.     if (set[c >> 3] & 1 << (c & 7))
  2437. #else
  2438.     if (set[c / BITSPERBYTE] & 1 << (c % BITSPERBYTE))
  2439. #endif
  2440.     return af;
  2441.     return !af;
  2442. }
  2443. !STUFFY!FUNK!
  2444. echo Extracting ngstuff.c
  2445. cat >ngstuff.c <<'!STUFFY!FUNK!'
  2446. /* $Header: ngstuff.c,v 4.3 85/05/01 11:45:03 lwall Exp $
  2447.  *
  2448.  * $Log:    ngstuff.c,v $
  2449.  * Revision 4.3  85/05/01  11:45:03  lwall
  2450.  * Baseline for release with 4.3bsd.
  2451.  * 
  2452.  */
  2453.  
  2454. #include "EXTERN.h"
  2455. #include "common.h"
  2456. #include "term.h"
  2457. #include "util.h"
  2458. #include "ng.h"
  2459. #include "bits.h"
  2460. #include "intrp.h"
  2461. #include "cheat.h"
  2462. #include "head.h"
  2463. #include "final.h"
  2464. #include "sw.h"
  2465. #include "INTERN.h"
  2466. #include "ngstuff.h"
  2467.  
  2468. void
  2469. ngstuff_init()
  2470. {
  2471.     ;
  2472. }
  2473.  
  2474. /* do a shell escape */
  2475.  
  2476. int
  2477. escapade()
  2478. {
  2479.     register char *s;
  2480.     bool interactive = (buf[1] == FINISHCMD);
  2481.     bool docd;
  2482.     char whereiam[256];
  2483.  
  2484.     if (!finish_command(interactive))    /* get remainder of command */
  2485.     return -1;
  2486.     s = buf+1;
  2487.     docd = *s != '!';
  2488.     if (!docd) {
  2489.     s++;
  2490.     }
  2491.     else {
  2492.     getwd(whereiam);
  2493.     if (chdir(cwd)) {
  2494.         printf(nocd,cwd) FLUSH;
  2495.         sig_catcher(0);
  2496.     }
  2497.     }
  2498.     while (*s == ' ') s++;
  2499.                     /* skip leading spaces */
  2500.     interp(cmd_buf, (sizeof cmd_buf), s);/* interpret any % escapes */
  2501.     resetty();                /* make sure tty is friendly */
  2502.     doshell(Nullch,cmd_buf);    /* invoke the shell */
  2503.     noecho();                /* and make terminal */
  2504.     crmode();                /*   unfriendly again */
  2505.     if (docd) {
  2506.     if (chdir(whereiam)) {
  2507.         printf(nocd,whereiam) FLUSH;
  2508.         sig_catcher(0);
  2509.     }
  2510.     }
  2511. #ifdef MAILCALL;
  2512.     mailcount = 0;            /* force recheck */
  2513. #endif
  2514.     return 0;
  2515. }
  2516.  
  2517. /* process & command */
  2518.  
  2519. int
  2520. switcheroo()
  2521. {
  2522.     if (!finish_command(TRUE)) /* get rest of command */
  2523.     return -1;    /* if rubbed out, try something else */
  2524.     if (!buf[1])
  2525.     pr_switches();
  2526. #ifdef PUSHBACK
  2527.     else if (buf[1] == '&') {
  2528.     if (!buf[2]) {
  2529.         page_init();
  2530.         show_macros();
  2531.     }
  2532.     else {
  2533.         char tmpbuf[LBUFLEN];
  2534.         register char *s;
  2535.  
  2536.         for (s=buf+2; isspace(*s); s++);
  2537.         mac_line(s,tmpbuf,(sizeof tmpbuf));
  2538.     }
  2539.     }
  2540. #endif
  2541.     else {
  2542.     bool docd = (instr(buf,"-d") != Nullch);
  2543.      char whereami[256];
  2544.  
  2545.     if (docd)
  2546.         getwd(whereami);
  2547.     sw_list(buf+1);
  2548.     if (docd) {
  2549.         cwd_check();
  2550.         if (chdir(whereami)) {        /* -d does chdirs */
  2551.         printf(nocd,whereami) FLUSH;
  2552.         sig_catcher(0);
  2553.         }
  2554.     }
  2555.     }
  2556.     return 0;
  2557. }
  2558.  
  2559. /* process range commands */
  2560.  
  2561. int
  2562. numnum()
  2563. {
  2564.     ART_NUM min, max;
  2565.     char *cmdlst = Nullch;
  2566.     register char *s, *c;
  2567.     ART_NUM oldart = art;
  2568.     char tmpbuf[LBUFLEN];
  2569.     bool justone = TRUE;        /* assume only one article */
  2570.  
  2571.     if (!finish_command(TRUE))    /* get rest of command */
  2572.     return NN_INP;
  2573.     if (lastart < 1) {
  2574.         fputs("\nNo articles\n",stdout) FLUSH;
  2575.         return NN_ASK;
  2576.     }
  2577. #ifdef ARTSRCH
  2578.     if (srchahead)
  2579.     srchahead = -1;
  2580. #endif
  2581.     for (s=buf; *s && (isdigit(*s) || index(" ,-.$",*s)); s++)
  2582.     if (!isdigit(*s))
  2583.         justone = FALSE;
  2584.     if (*s) {
  2585.     cmdlst = savestr(s);
  2586.     justone = FALSE;
  2587.     }
  2588.     else if (!justone)
  2589.     cmdlst = savestr("m");
  2590.     *s++ = ',';
  2591.     *s = '\0';
  2592.     safecpy(tmpbuf,buf,LBUFLEN);
  2593.     for (s = tmpbuf; c = index(s,','); s = ++c) {
  2594.     *c = '\0';
  2595.     if (*s == '.')
  2596.         min = oldart;
  2597.     else
  2598.         min = atol(s);
  2599.     if (min<absfirst) {        /* make sure it is reasonable */
  2600.         min = absfirst;
  2601.         printf("(First article is %ld)\n",(long)absfirst) FLUSH;
  2602.         pad(just_a_sec/3);
  2603.     }
  2604.     if ((s=index(s,'-')) != Nullch) {
  2605.         s++;
  2606.         if (*s == '$')
  2607.         max = lastart;
  2608.         else if (*s == '.')
  2609.         max = oldart;
  2610.         else
  2611.         max = atol(s);
  2612.     }
  2613.     else
  2614.         max = min;
  2615.     if (max>lastart) {
  2616.         max = lastart;
  2617.         if (min > max)
  2618.         min = max;
  2619.         printf("(Last article is %ld)\n",(long)lastart) FLUSH;
  2620.         pad(just_a_sec/3);
  2621.     }
  2622.     if (max < min) {
  2623.         fputs("\nBad range\n",stdout) FLUSH;
  2624.         if (cmdlst)
  2625.         free(cmdlst);
  2626.         return NN_ASK;
  2627.     }
  2628.     if (justone) {
  2629.         art = min;
  2630.         return NN_REREAD;
  2631.     }
  2632.     check_first(min);
  2633.     for (art=min; art<=max; art++) {
  2634.         if (perform(cmdlst,TRUE)) {
  2635. #ifdef VERBOSE
  2636.         IF(verbose)
  2637.             printf("\n(Interrupted at article %ld)\n",(long)art)
  2638.               FLUSH;
  2639.         ELSE
  2640. #endif
  2641. #ifdef TERSE
  2642.             printf("\n(Intr at %ld)\n",(long)art) FLUSH;
  2643. #endif
  2644.         if (cmdlst)
  2645.             free(cmdlst);
  2646.         return NN_ASK;
  2647.         }
  2648.     }
  2649.     }
  2650.     art = oldart;
  2651.     if (cmdlst)
  2652.     free(cmdlst);
  2653.     return NN_NORM;
  2654. }
  2655.  
  2656. int
  2657. perform(cmdlst,toplevel)
  2658. register char *cmdlst;
  2659. int toplevel;
  2660. {
  2661.     register int ch;
  2662.     
  2663.     if (toplevel) {
  2664.     printf("%-6ld",art);
  2665.     fflush(stdout);
  2666.     }
  2667.     for (; ch = *cmdlst; cmdlst++) {
  2668.     if (isspace(ch) || ch == ':')
  2669.         continue;
  2670.     if (ch == 'j') {
  2671.         mark_as_read(art);
  2672. #ifdef VERBOSE
  2673.         IF(verbose)
  2674.             fputs("\tJunked",stdout);
  2675. #endif
  2676.     }
  2677.     else if (ch == 'm') {
  2678.         unmark_as_read(art);
  2679. #ifdef VERBOSE
  2680.         IF(verbose)
  2681.             fputs("\tMarked unread",stdout);
  2682. #endif
  2683.     }
  2684.     else if (ch == 'M') {
  2685. #ifdef DELAYMARK
  2686.         delay_unmark(art);
  2687. #ifdef VERBOSE
  2688.         IF(verbose)
  2689.             fputs("\tWill return",stdout);
  2690. #endif
  2691. #else
  2692.         notincl("M");
  2693.         return -1;
  2694. #endif
  2695.     }
  2696.     else if (ch == '=') {
  2697.         printf("\t%s",fetchsubj(art,FALSE,FALSE));
  2698. #ifdef VERBOSE
  2699.         IF(verbose)
  2700.         ;
  2701.         ELSE
  2702. #endif
  2703.         putchar('\n') FLUSH;        /* ghad! */
  2704.     }
  2705.     else if (ch == 'C') {
  2706. #ifdef ASYNC_PARSE
  2707.         printf("\t%sancelled",(cancel_article() ? "Not c" : "C"));
  2708. #else
  2709.         notincl("C");
  2710.         return -1;
  2711. #endif
  2712.     }
  2713.     else if (ch == '%') {
  2714. #ifdef ASYNC_PARSE
  2715.         char tmpbuf[512];
  2716.  
  2717.         cmdlst = dointerp(tmpbuf, (sizeof tmpbuf), cmdlst,":");
  2718.         if (*cmdlst != ':')
  2719.         --cmdlst;
  2720.         if (perform(tmpbuf,FALSE))
  2721.         return -1;
  2722. #else
  2723.         notincl("%");
  2724.         return -1;
  2725. #endif
  2726.     }
  2727.     else if (index("!&sSwW|",ch)) {
  2728.         cmdlst = cpytill(buf,cmdlst,':') - 1;
  2729.         /* we now have the command in buf */
  2730.         if (ch == '!') {
  2731.         escapade();
  2732. #ifdef VERBOSE
  2733.         IF(verbose)
  2734.             fputs("\tShell escaped",stdout);
  2735. #endif
  2736.         }
  2737.         else if (ch == '&') {
  2738.         switcheroo();
  2739. #ifdef VERBOSE
  2740.         IF(verbose)
  2741.             fputs("\tSwitched",stdout);
  2742. #endif
  2743.         }
  2744.         else {
  2745.         putchar('\t');
  2746.         save_article();
  2747.         }
  2748.     }
  2749.     else {
  2750.         printf("\t???%s\n",cmdlst);
  2751.         return -1;
  2752.     }
  2753. #ifdef VERBOSE
  2754.     fflush(stdout);
  2755. #endif
  2756.     }
  2757.     if (toplevel) {
  2758. #ifdef VERBOSE
  2759.     IF(verbose)
  2760.         putchar('\n') FLUSH;
  2761.     ELSE
  2762. #endif
  2763. #ifdef TERSE
  2764.         putchar(' ');
  2765. #endif
  2766.     }
  2767.     return 0;
  2768. }
  2769.  
  2770. !STUFFY!FUNK!
  2771. echo Extracting makedist
  2772. cat >makedist <<'!STUFFY!FUNK!'
  2773. #!/bin/sh
  2774. # $Header: makedist,v 4.3 85/05/01 11:42:35 lwall Exp $
  2775. #
  2776. # $Log:    makedist,v $
  2777. # Revision 4.3  85/05/01  11:42:35  lwall
  2778. # Baseline for release with 4.3bsd.
  2779.  
  2780. rm -f kit*.list
  2781. manifake
  2782. kitlists
  2783. manimake
  2784. makekit kit*.list
  2785. !STUFFY!FUNK!
  2786. echo ""
  2787. echo "End of kit 4 (of 9)"
  2788. cat /dev/null >kit4isdone
  2789. config=true
  2790. for iskit in 1 2 3 4 5 6 7 8 9; do
  2791.     if test -f kit${iskit}isdone; then
  2792.     echo "You have run kit ${iskit}."
  2793.     else
  2794.     echo "You still need to run kit ${iskit}."
  2795.     config=false
  2796.     fi
  2797. done
  2798. case $config in
  2799.     true)
  2800.     echo "You have run all your kits.  Please read README and then type Configure."
  2801.     chmod 755 Configure
  2802.     ;;
  2803. esac
  2804. : I do not append .signature, but someone might mail this.
  2805. exit
  2806.  
  2807.