home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / EXEC.C < prev    next >
C/C++ Source or Header  |  1991-10-10  |  33KB  |  1,489 lines

  1. /*    This file is for functions dealing with execution of
  2.     commands, command lines, buffers, files and startup files
  3.  
  4.     written 1986 by Daniel Lawrence                */
  5.  
  6. #include    <stdio.h>
  7. #include    "estruct.h"
  8. #include    "eproto.h"
  9. #include    "edef.h"
  10. #include    "elang.h"
  11.  
  12. /* namedcmd:    execute a named command even if it is not bound */
  13.  
  14. PASCAL NEAR namedcmd(f, n)
  15.  
  16. int f, n;    /* command arguments [passed through to command executed] */
  17.  
  18. {
  19.     int (PASCAL NEAR *kfunc)();     /* ptr to the function to execute */
  20.     char buffer[NSTRING];        /* buffer to store function name */
  21.     int status;
  22.  
  23.     /* if we are non-interactive.... force the command interactivly */
  24.     if (clexec == TRUE) {
  25.         /* grab token and advance past */
  26.         execstr = token(execstr, buffer, NPAT);
  27.  
  28.         /* evaluate it */
  29.         strcpy(buffer, fixnull(getval(buffer)));
  30.         if (strcmp(buffer, errorm) == 0)
  31.             return(FALSE);
  32.  
  33.         /* and look it up */
  34.         if ((kfunc = fncmatch(buffer)) == NULL) {
  35.             mlwrite(TEXT16);
  36. /*                          "[No such Function]" */
  37.             return(FALSE);
  38.         }
  39.         
  40.         /* and execute it  INTERACTIVE */
  41.         clexec = FALSE;
  42.         status = (*kfunc)(f, n);    /* call the function */
  43.         clexec = TRUE;
  44.         return(status);
  45.     }
  46.  
  47.     /* prompt the user to type a named command */
  48.     /* and get the function name to execute */
  49.     kfunc = getname(": ");
  50.     if (kfunc == NULL) {
  51.         mlwrite(TEXT16);
  52. /*                      "[No such function]" */
  53.         return(FALSE);
  54.     }
  55.  
  56.     /* and then execute the command */
  57.     return((*kfunc)(f, n));
  58. }
  59.  
  60. /*    execcmd:    Execute a command line command to be typed in
  61.             by the user                    */
  62.  
  63. PASCAL NEAR execcmd(f, n)
  64.  
  65. int f, n;    /* default Flag and Numeric argument */
  66.  
  67. {
  68.     register int status;        /* status return */
  69.     char cmdstr[NSTRING];        /* string holding command to execute */
  70.  
  71.     /* get the line wanted */
  72.     if ((status = mlreply(": ", cmdstr, NSTRING)) != TRUE)
  73.         return(status);
  74.  
  75.     execlevel = 0;
  76.     return(docmd(cmdstr));
  77. }
  78.  
  79. /*    docmd:    take a passed string as a command line and translate
  80.         it to be executed as a command. This function will be
  81.         used by execute-command-line and by all source and
  82.         startup files. Lastflag/thisflag is also updated.
  83.  
  84.     format of the command line is:
  85.  
  86.         {# arg} <command-name> {<argument string(s)>}
  87.  
  88. */
  89.  
  90. PASCAL NEAR docmd(cline)
  91.  
  92. char *cline;    /* command line to execute */
  93.  
  94. {
  95.     register int f;        /* default argument flag */
  96.     register int n;        /* numeric repeat value */
  97.     int (PASCAL NEAR *fnc)();/* function to execute */
  98.     BUFFER *bp;        /* buffer to execute */
  99.     int status;        /* return status of function */
  100.     int oldcle;        /* old contents of clexec flag */
  101.     char *oldestr;        /* original exec string */
  102.     char tkn[NSTRING];    /* next token off of command line */
  103.         char bufn[NBUFN+2];    /* name of buffer to execute */
  104.  
  105.     /* if we are scanning and not executing..go back here */
  106.     if (execlevel)
  107.         return(TRUE);
  108.  
  109.     oldestr = execstr;    /* save last ptr to string to execute */
  110.     execstr = cline;    /* and set this one as current */
  111.  
  112.     /* first set up the default command values */
  113.     f = FALSE;
  114.     n = 1;
  115.     lastflag = thisflag;
  116.     thisflag = 0;
  117.  
  118.     if ((status = macarg(tkn)) != TRUE) {    /* and grab the first token */
  119.         execstr = oldestr;
  120.         return(status);
  121.     }
  122.  
  123.     /* process leadin argument */
  124.     if (gettyp(tkn) != TKCMD) {
  125.         f = TRUE;
  126.         strcpy(tkn, fixnull(getval(tkn)));
  127.         n = asc_int(tkn);
  128.  
  129.         /* and now get the command to execute */
  130.         if ((status = macarg(tkn)) != TRUE) {
  131.             execstr = oldestr;
  132.             return(status);
  133.         }
  134.     }
  135.  
  136.     /* and match the token to see if it exists */
  137.     if ((fnc = fncmatch(tkn)) == NULL) {
  138.  
  139.         /* construct the buffer name */
  140.         strcpy(bufn, "[");
  141.         strcat(bufn, tkn);
  142.         strcat(bufn, "]");
  143.  
  144.         /* find the pointer to that buffer */
  145.             if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  146.             mlwrite(TEXT16);
  147. /*                          "[No such Function]" */
  148.             execstr = oldestr;
  149.             return(FALSE);
  150.         }
  151.  
  152.         /* execute the buffer */
  153.         oldcle = clexec;    /* save old clexec flag */
  154.         clexec = TRUE;        /* in cline execution */
  155.         while (n-- > 0)
  156.             if ((status = dobuf(bp)) != TRUE)
  157.                 break;
  158.         cmdstatus = status;    /* save the status */
  159.         clexec = oldcle;    /* restore clexec flag */
  160.         execstr = oldestr;
  161.         return(status);
  162.     }
  163.     
  164.     /* save the arguments and go execute the command */
  165.     oldcle = clexec;        /* save old clexec flag */
  166.     clexec = TRUE;            /* in cline execution */
  167.     status = (*fnc)(f, n);        /* call the function */
  168.     cmdstatus = status;        /* save the status */
  169.     clexec = oldcle;        /* restore clexec flag */
  170.     execstr = oldestr;
  171.     return(status);
  172. }
  173.  
  174. /* token:    chop a token off a string
  175.         return a pointer past the token
  176. */
  177.  
  178. char *PASCAL NEAR token(src, tok, size)
  179.  
  180. char *src, *tok;    /* source string, destination token string */
  181. int size;        /* maximum size of token */
  182.  
  183. {
  184.     register int quotef;    /* is the current string quoted? */
  185.     register char c;    /* temporary character */
  186.  
  187.     /* first scan past any whitespace in the source string */
  188.     while (*src == ' ' || *src == '\t')
  189.         ++src;
  190.  
  191.     /* scan through the source string */
  192.     quotef = FALSE;
  193.     while (*src) {
  194.         /* process special characters */
  195.         if (*src == '~') {
  196.             ++src;
  197.             if (*src == 0)
  198.                 break;
  199.             switch (*src++) {
  200.                 case 'r':    c = 13; break;
  201.                 case 'n':    c = 13; break;
  202.                 case 'l':    c = 10; break;
  203.                 case 't':    c = 9;  break;
  204.                 case 'b':    c = 8;  break;
  205.                 case 'f':    c = 12; break;
  206.                 default:    c = *(src-1);
  207.             }
  208.             if (--size > 0) {
  209.                 *tok++ = c;
  210.             }
  211.         } else {
  212.             /* check for the end of the token */
  213.             if (quotef) {
  214.                 if (*src == '"')
  215.                     break;
  216.             } else {
  217.                 if (*src == ' ' || *src == '\t')
  218.                     break;
  219.             }
  220.  
  221.             /* set quote mode if quote found */
  222.             if (*src == '"')
  223.                 quotef = TRUE;
  224.  
  225.             /* record the character */
  226.             c = *src++;
  227.             if (--size > 0)
  228.                 *tok++ = c;
  229.         }
  230.     }
  231.  
  232.     /* terminate the token and exit */
  233.     if (*src)
  234.         ++src;
  235.     *tok = 0;
  236.     return(src);
  237. }
  238.  
  239. PASCAL NEAR macarg(tok)    /* get a macro line argument */
  240.  
  241. char *tok;    /* buffer to place argument */
  242.  
  243. {
  244.     int savcle;    /* buffer to store original clexec */
  245.     int status;
  246.  
  247.     savcle = clexec;    /* save execution mode */
  248.     clexec = TRUE;        /* get the argument */
  249.     status = nextarg("", tok, NSTRING, ctoec('\r'));
  250.     clexec = savcle;    /* restore execution mode */
  251.     return(status);
  252. }
  253.  
  254. /*    nextarg:    get the next argument    */
  255.  
  256. PASCAL NEAR nextarg(prompt, buffer, size, terminator)
  257.  
  258. char *prompt;        /* prompt to use if we must be interactive */
  259. char *buffer;        /* buffer to put token into */
  260. int size;        /* size of the buffer */
  261. int terminator;        /* terminating char to be used on interactive fetch */
  262.  
  263. {
  264.     register char *sp;    /* return pointer from getval() */
  265.  
  266.     /* if we are interactive, go get it! */
  267.     if (clexec == FALSE)
  268.         return(getstring(prompt, buffer, size, terminator));
  269.  
  270.     /* grab token and advance past */
  271.     execstr = token(execstr, buffer, size);
  272.  
  273.     /* evaluate it */
  274.     if ((sp = getval(buffer)) == NULL)
  275.         return(FALSE);
  276.     strcpy(buffer, sp);
  277.     return(TRUE);
  278. }
  279.  
  280. /*    storemac:    Set up a macro buffer and flag to store all
  281.             executed command lines there            */
  282.  
  283. PASCAL NEAR storemac(f, n)
  284.  
  285. int f;        /* default flag */
  286. int n;        /* macro number to use */
  287.  
  288. {
  289.     register struct BUFFER *bp;    /* pointer to macro buffer */
  290.     char bname[NBUFN];        /* name of buffer to use */
  291.  
  292.     /* must have a numeric argument to this function */
  293.     if (f == FALSE) {
  294.         mlwrite(TEXT111);
  295. /*                      "No macro specified" */
  296.         return(FALSE);
  297.     }
  298.  
  299.     /* range check the macro number */
  300.     if (n < 1 || n > 40) {
  301.         mlwrite(TEXT112);
  302. /*                      "Macro number out of range" */
  303.         return(FALSE);
  304.     }
  305.  
  306.     /* construct the macro buffer name */
  307.     strcpy(bname, "[Macro xx]");
  308.     bname[7] = '0' + (n / 10);
  309.     bname[8] = '0' + (n % 10);
  310.  
  311.     /* set up the new macro buffer */
  312.     if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
  313.         mlwrite(TEXT113);
  314. /*                      "Can not create macro" */
  315.         return(FALSE);
  316.     }
  317.  
  318.     /* and make sure it is empty */
  319.     bclear(bp);
  320.  
  321.     /* and set the macro store pointers to it */
  322.     mstore = TRUE;
  323.     bstore = bp;
  324.     return(TRUE);
  325. }
  326.  
  327. /*    storeproc:    Set up a procedure buffer and flag to store all
  328.             executed command lines there            */
  329.  
  330. PASCAL NEAR storeproc(f, n)
  331.  
  332. int f;        /* default flag */
  333. int n;        /* macro number to use */
  334.  
  335. {
  336.     register struct BUFFER *bp;    /* pointer to macro buffer */
  337.     register int status;        /* return status */
  338.     char bname[NBUFN];        /* name of buffer to use */
  339.  
  340.     /* a numeric argument means its a numbered macro */
  341.     if (f == TRUE)
  342.         return(storemac(f, n));
  343.  
  344.     /* get the name of the procedure */
  345.         if ((status = mlreply(TEXT114, &bname[1], NBUFN-2)) != TRUE)
  346. /*                            "Procedure name: " */
  347.                 return(status);
  348.  
  349.     /* construct the macro buffer name */
  350.     bname[0] = '[';
  351.     strcat(bname, "]");
  352.  
  353.     /* set up the new macro buffer */
  354.     if ((bp = bfind(bname, TRUE, BFINVS)) == NULL) {
  355.         mlwrite(TEXT113);
  356. /*                      "Can not create macro" */
  357.         return(FALSE);
  358.     }
  359.  
  360.     /* and make sure it is empty */
  361.     bclear(bp);
  362.  
  363.     /* and set the macro store pointers to it */
  364.     mstore = TRUE;
  365.     bstore = bp;
  366.     return(TRUE);
  367. }
  368.  
  369. /*    execproc:    Execute a procedure                */
  370.  
  371. PASCAL NEAR execproc(f, n)
  372.  
  373. int f, n;    /* default flag and numeric arg */
  374.  
  375. {
  376.         register BUFFER *bp;        /* ptr to buffer to execute */
  377.         register int status;        /* status return */
  378.         char bufn[NBUFN+2];        /* name of buffer to execute */
  379.  
  380.     /* find out what buffer the user wants to execute */
  381.         if ((status = mlreply(TEXT115, &bufn[1], NBUFN)) != TRUE)
  382. /*                            "Execute procedure: " */
  383.                 return(status);
  384.  
  385.     /* construct the buffer name */
  386.     bufn[0] = '[';
  387.     strcat(bufn, "]");
  388.  
  389.     /* find the pointer to that buffer */
  390.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  391.         mlwrite(TEXT116);
  392. /*                      "No such procedure" */
  393.                 return(FALSE);
  394.         }
  395.  
  396.     /* and now execute it as asked */
  397.     while (n-- > 0)
  398.         if ((status = dobuf(bp)) != TRUE)
  399.             return(status);
  400.     return(TRUE);
  401. }
  402.  
  403. /*    execbuf:    Execute the contents of a buffer of commands    */
  404.  
  405. PASCAL NEAR execbuf(f, n)
  406.  
  407. int f, n;    /* default flag and numeric arg */
  408.  
  409. {
  410.         register BUFFER *bp;        /* ptr to buffer to execute */
  411.         register int status;        /* status return */
  412.         char bufn[NSTRING];        /* name of buffer to execute */
  413.  
  414.     /* find out what buffer the user wants to execute */
  415.         if ((status = mlreply(TEXT117, bufn, NBUFN)) != TRUE)
  416. /*                            "Execute buffer: " */
  417.                 return(status);
  418.  
  419.     /* find the pointer to that buffer */
  420.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) {
  421.         mlwrite(TEXT118);
  422. /*                      "No such buffer" */
  423.                 return(FALSE);
  424.         }
  425.  
  426.     /* and now execute it as asked */
  427.     while (n-- > 0)
  428.         if ((status = dobuf(bp)) != TRUE)
  429.             return(status);
  430.     return(TRUE);
  431. }
  432.  
  433. /*    dobuf:    execute the contents of the buffer pointed to
  434.         by the passed BP
  435.  
  436.     Directives start with a "!" and include:
  437.  
  438.     !endm        End a macro
  439.     !if (cond)    conditional execution
  440.     !else
  441.     !endif
  442.     !return        Return (terminating current macro)
  443.     !goto <label>    Jump to a label in the current macro
  444.     !force        Force macro to continue...even if command fails
  445.     !while (cond)    Execute a loop if the condition is true
  446.     !endwhile
  447.     
  448.     Line Labels begin with a "*" as the first nonblank char, like:
  449.  
  450.     *LBL01
  451. */
  452.  
  453. PASCAL NEAR dobuf(bp)
  454.  
  455. BUFFER *bp;    /* buffer to execute */
  456.  
  457. {
  458.         register int status;    /* status return */
  459.     register LINE *lp;    /* pointer to line to execute */
  460.     register LINE *hlp;    /* pointer to line header */
  461.     register LINE *glp;    /* line to goto */
  462.     LINE *mp;        /* Macro line storage temp */
  463.     int dirnum;        /* directive index */
  464.     int linlen;        /* length of line to execute */
  465.     int i;            /* index */
  466.     int force;        /* force TRUE result? */
  467.     WINDOW *wp;        /* ptr to windows to scan */
  468.     WHBLOCK *whlist;    /* ptr to !WHILE list */
  469.     WHBLOCK *scanner;    /* ptr during scan */
  470.     WHBLOCK *whtemp;    /* temporary ptr to a WHBLOCK */
  471.     char *einit;        /* initial value of eline */
  472.     char *eline;        /* text of line to execute */
  473.     char tkn[NSTRING];    /* buffer to evaluate an expresion in */
  474. #if    LOGFLG
  475.     FILE *fp;        /* file handle for log file */
  476. #endif
  477. #if    DEBUGM
  478.     int skipflag;        /* are we skipping debugging a function? */
  479. #endif
  480.  
  481.     /* clear IF level flags/while ptr */
  482.     execlevel = 0;
  483.     whlist = NULL;
  484.     scanner = NULL;
  485.  
  486.     /* flag we are executing the buffer */
  487.     bp->b_exec += 1;
  488.  
  489. #if    DEBUGM
  490.     /* we are not skipping a function yet (for the debugger) */
  491.     skipflag = FALSE;
  492. #endif
  493.  
  494.     /* scan the buffer to execute, building WHILE header blocks */
  495.     hlp = bp->b_linep;
  496.     lp = hlp->l_fp;
  497.     while (lp != hlp) {
  498.         /* scan the current line */
  499.         eline = lp->l_text;
  500.         i = lp->l_used;
  501.  
  502.         /* trim leading whitespace */
  503.         while (i-- > 0 && (*eline == ' ' || *eline == '\t'))
  504.             ++eline;
  505.  
  506.         /* if theres nothing here, don't bother */
  507.         if (i <= 0)
  508.             goto nxtscan;
  509.  
  510.         /* if is a while directive, make a block... */
  511.         if (eline[0] == '!' && eline[1] == 'w' && eline[2] == 'h') {
  512.             whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
  513.             if (whtemp == NULL) {
  514. noram:                errormesg(TEXT119, bp, lp);
  515. /*                                        "%%Out of memory during while scan" */
  516. failexit:            freewhile(scanner);
  517.                 freewhile(whlist);
  518.                 bp->b_exec -= 1;
  519.                 return(FALSE);
  520.             }
  521.             whtemp->w_begin = lp;
  522.             whtemp->w_type = BTWHILE;
  523.             whtemp->w_next = scanner;
  524.             scanner = whtemp;
  525.         }
  526.  
  527.         /* if is a BREAK directive, make a block... */
  528.         if (eline[0] == '!' && eline[1] == 'b' && eline[2] == 'r') {
  529.             if (scanner == NULL) {
  530.                 errormesg(TEXT120, bp, lp);
  531. /*                                        "%%!BREAK outside of any !WHILE loop" */
  532.                 goto failexit;
  533.             }
  534.             whtemp = (WHBLOCK *)malloc(sizeof(WHBLOCK));
  535.             if (whtemp == NULL)
  536.                 goto noram;
  537.             whtemp->w_begin = lp;
  538.             whtemp->w_type = BTBREAK;
  539.             whtemp->w_next = scanner;
  540.             scanner = whtemp;
  541.         }
  542.  
  543.         /* if it is an endwhile directive, record the spot... */
  544.         if (eline[0] == '!' && strncmp(&eline[1], "endw", 4) == 0) {
  545.             if (scanner == NULL) {
  546.                 errormesg(TEXT121, bp, lp);
  547. /*                                      "%%!ENDWHILE with no preceding !WHILE" */
  548.                 goto failexit;
  549.             }
  550.             /* move top records from the scanner list to the
  551.                whlist until we have moved all BREAK records
  552.                and one WHILE record */
  553.             do {
  554.                 scanner->w_end = lp;
  555.                 whtemp = whlist;
  556.                 whlist = scanner;
  557.                 scanner = scanner->w_next;
  558.                 whlist->w_next = whtemp;
  559.             } while (whlist->w_type == BTBREAK);
  560.         }
  561.  
  562. nxtscan:    /* on to the next line */
  563.         lp = lp->l_fp;
  564.     }
  565.  
  566.     /* while and endwhile should match! */
  567.     if (scanner != NULL) {
  568.         errormesg(TEXT122, bp, lp);
  569. /*                      "%%!WHILE with no matching !ENDWHILE" */
  570.         goto failexit;
  571.     }
  572.  
  573.     /* let the first command inherit the flags from the last one..*/
  574.     thisflag = lastflag;
  575.  
  576.     /* starting at the beginning of the buffer */
  577.     hlp = bp->b_linep;
  578.     lp = hlp->l_fp;
  579.     while (lp != hlp && eexitflag == FALSE) {
  580.  
  581.         /* allocate eline and copy macro line to it */
  582.         linlen = lp->l_used;
  583.         if ((einit = eline = malloc(linlen+1)) == NULL) {
  584.             errormesg(TEXT123, bp, lp);
  585. /*                              "%%Out of Memory during macro execution" */
  586.             freewhile(whlist);
  587.             bp->b_exec -= 1;
  588.             return(FALSE);
  589.         }
  590.         bytecopy(eline, lp->l_text, linlen);
  591.         eline[linlen] = 0;    /* make sure it ends */
  592.  
  593.         /* trim leading whitespace */
  594.         while (*eline == ' ' || *eline == '\t')
  595.             ++eline;
  596.  
  597.         /* dump comments and blank lines */
  598.         if (*eline == ';' || *eline == 0)
  599.             goto onward;
  600.  
  601. #if    LOGFLG
  602.         /* append the current command to the log file */
  603.         fp = fopen("emacs.log", "a");
  604.         strcpy(outline, eline);
  605.         fprintf(fp, "%s\n", outline);
  606.         fclose(fp);
  607. #endif
  608.     
  609. #if    DEBUGM
  610.         /* only do this if we are debugging */
  611.         if (macbug && !mstore && (execlevel == 0))
  612.             if (debug(bp, eline, &skipflag) == FALSE) {
  613.                 errormesg(TEXT54, bp, lp);
  614. /*                                      "[Macro aborted]" */
  615.                 freewhile(whlist);
  616.                 bp->b_exec -= 1;
  617.                 return(FALSE);
  618.             }
  619. #endif
  620.  
  621.         /* Parse directives here.... */
  622.         dirnum = -1;
  623.         if (*eline == '!') {
  624.             /* Find out which directive this is */
  625.             ++eline;
  626.             for (dirnum = 0; dirnum < NUMDIRS; dirnum++)
  627.                 if (strncmp(eline, dname[dirnum],
  628.                             strlen(dname[dirnum])) == 0)
  629.                     break;
  630.  
  631.             /* and bitch if it's illegal */
  632.             if (dirnum == NUMDIRS) {
  633.                 errormesg(TEXT124, bp, lp);
  634. /*                                      "%%Unknown Directive" */
  635.                 freewhile(whlist);
  636.                 bp->b_exec -= 1;
  637.                 return(FALSE);
  638.             }
  639.  
  640.             /* service only the !ENDM macro here */
  641.             if (dirnum == DENDM) {
  642.                 mstore = FALSE;
  643.                 bstore = NULL;
  644.                 goto onward;
  645.             }
  646.  
  647.             /* restore the original eline....*/
  648.             --eline;
  649.         }
  650.  
  651.         /* if macro store is on, just salt this away */
  652.         if (mstore) {
  653.             /* allocate the space for the line */
  654.             linlen = strlen(eline);
  655.             if ((mp=lalloc(linlen)) == NULL) {
  656.                 errormesg(TEXT125, bp, lp);
  657. /*                                      "Out of memory while storing macro" */
  658.                 bp->b_exec -= 1;
  659.                 return(FALSE);
  660.             }
  661.     
  662.             /* copy the text into the new line */
  663.             for (i=0; i<linlen; ++i)
  664.                 lputc(mp, i, eline[i]);
  665.     
  666.             /* attach the line to the end of the buffer */
  667.                    bstore->b_linep->l_bp->l_fp = mp;
  668.             mp->l_bp = bstore->b_linep->l_bp;
  669.             bstore->b_linep->l_bp = mp;
  670.             mp->l_fp = bstore->b_linep;
  671.             goto onward;
  672.         }
  673.     
  674.         force = FALSE;
  675.  
  676.         /* dump comments */
  677.         if (*eline == '*')
  678.             goto onward;
  679.  
  680.         /* now, execute directives */
  681.         if (dirnum != -1) {
  682.             /* skip past the directive */
  683.             while (*eline && *eline != ' ' && *eline != '\t')
  684.                 ++eline;
  685.             execstr = eline;
  686.  
  687.             switch (dirnum) {
  688.             case DIF:    /* IF directive */
  689.                 /* grab the value of the logical exp */
  690.                 if (execlevel == 0) {
  691.                     if (macarg(tkn) != TRUE)
  692.                         goto eexec;
  693.                     if (stol(tkn) == FALSE)
  694.                         ++execlevel;
  695.                 } else
  696.                     ++execlevel;
  697.                 goto onward;
  698.  
  699.             case DWHILE:    /* WHILE directive */
  700.                 /* grab the value of the logical exp */
  701.                 if (execlevel == 0) {
  702.                     if (macarg(tkn) != TRUE)
  703.                         goto eexec;
  704.                     if (stol(tkn) == TRUE)
  705.                         goto onward;
  706.                 }
  707.                 /* drop down and act just like !BREAK */
  708.  
  709.             case DBREAK:    /* BREAK directive */
  710.                 if (dirnum == DBREAK && execlevel)
  711.                     goto onward;
  712.  
  713.                 /* jump down to the endwhile */
  714.                 /* find the right while loop */
  715.                 whtemp = whlist;
  716.                 while (whtemp) {
  717.                     if (whtemp->w_begin == lp)
  718.                         break;
  719.                     whtemp = whtemp->w_next;
  720.                 }
  721.             
  722.                 if (whtemp == NULL) {
  723.                     errormesg(TEXT126, bp, lp);
  724. /*                                              "%%Internal While loop error" */
  725.                     freewhile(whlist);
  726.                     bp->b_exec -= 1;
  727.                     return(FALSE);
  728.                 }
  729.             
  730.                 /* reset the line pointer back.. */
  731.                 lp = whtemp->w_end;
  732.                 goto onward;
  733.  
  734.             case DELSE:    /* ELSE directive */
  735.                 if (execlevel == 1)
  736.                     --execlevel;
  737.                 else if (execlevel == 0 )
  738.                     ++execlevel;
  739.                 goto onward;
  740.  
  741.             case DENDIF:    /* ENDIF directive */
  742.                 if (execlevel)
  743.                     --execlevel;
  744.                 goto onward;
  745.  
  746.             case DGOTO:    /* GOTO directive */
  747.                 /* .....only if we are currently executing */
  748.                 if (execlevel == 0) {
  749.  
  750.                     /* grab label to jump to */
  751.                     eline = token(eline, golabel, NPAT);
  752.                     linlen = strlen(golabel);
  753.                     glp = hlp->l_fp;
  754.                     while (glp != hlp) {
  755.                         if (*glp->l_text == '*' &&
  756.                             (strncmp(&glp->l_text[1], golabel,
  757.                                     linlen) == 0)) {
  758.                             lp = glp;
  759.                             goto onward;
  760.                         }
  761.                         glp = glp->l_fp;
  762.                     }
  763.                     errormesg(TEXT127, bp, lp);
  764. /*                                              "%%No such label" */
  765.                     freewhile(whlist);
  766.                     bp->b_exec -= 1;
  767.                     return(FALSE);
  768.                 }
  769.                 goto onward;
  770.     
  771.             case DRETURN:    /* RETURN directive */
  772.                 if (execlevel == 0)
  773.                     goto eexec;
  774.                 goto onward;
  775.  
  776.             case DENDWHILE:    /* ENDWHILE directive */
  777.                 if (execlevel) {
  778.                     --execlevel;
  779.                     goto onward;
  780.                 } else {
  781.                     /* find the right while loop */
  782.                     whtemp = whlist;
  783.                     while (whtemp) {
  784.                         if (whtemp->w_type == BTWHILE &&
  785.                             whtemp->w_end == lp)
  786.                             break;
  787.                         whtemp = whtemp->w_next;
  788.                     }
  789.         
  790.                     if (whtemp == NULL) {
  791.                         errormesg(TEXT126, bp, lp);
  792. /*                                                      "%%Internal While loop error" */
  793.                         freewhile(whlist);
  794.                         bp->b_exec -= 1;
  795.                         return(FALSE);
  796.                     }
  797.         
  798.                     /* reset the line pointer back.. */
  799.                     lp = whtemp->w_begin->l_bp;
  800.                     goto onward;
  801.                 }
  802.  
  803.             case DFORCE:    /* FORCE directive */
  804.                 force = TRUE;
  805.  
  806.             }
  807.         }
  808.  
  809.         /* execute the statement */
  810.         status = docmd(eline);
  811.         if (force)        /* force the status */
  812.             status = TRUE;
  813.  
  814.         /* check for a command error */
  815.         if (status != TRUE) {
  816.  
  817.             /* look if buffer is showing */
  818.             wp = wheadp;
  819.             while (wp != NULL) {
  820.                 if (wp->w_bufp == bp) {
  821.                     /* and point it */
  822.                     wp->w_dotp = lp;
  823.                     wp->w_doto = 0;
  824.                     wp->w_flag |= WFHARD;
  825.                 }
  826.                 wp = wp->w_wndp;
  827.             }
  828.  
  829.             /* in any case set the buffer . */
  830.             bp->b_dotp = lp;
  831.             bp->b_doto = 0;
  832.             free(einit);
  833.             execlevel = 0;
  834.             freewhile(whlist);
  835.  
  836.             errormesg(TEXT219, bp, lp);
  837. /*                  "%%Macro Failed" */
  838.             bp->b_exec -= 1;
  839.             return(status);
  840.         }
  841.  
  842. onward:        /* on to the next line */
  843.         free(einit);
  844.         lp = lp->l_fp;
  845. #if    DEBUGM
  846.         if (skipflag)
  847.             macbug = TRUE;
  848. #endif
  849.     }
  850.  
  851. eexec:    /* exit the current function */
  852.     execlevel = 0;
  853.     freewhile(whlist);
  854.     bp->b_exec -= 1;
  855.         return(TRUE);
  856. }
  857.  
  858. /* errormesg:    display a macro execution error along with the buffer and
  859.         line currently being executed */
  860.  
  861. errormesg(mesg, bp, lp)
  862.  
  863. char *mesg;    /* error message to display */
  864. BUFFER *bp;    /* buffer error occured in */
  865. LINE *lp;    /* line " */
  866.  
  867. {
  868.     char buf[NSTRING];
  869.  
  870.     exec_error = TRUE;
  871.  
  872.     /* build error message line */
  873.     strcpy(buf, "\n");
  874.     strcat(buf, mesg);
  875.     strcat(buf, " in <");
  876.     strcat(buf, bp->b_bname);
  877.     strcat(buf, "> at line ");
  878.     strcat(buf, int_asc(getlinenum(bp, lp)));
  879.     mlforce(buf);
  880. }
  881.  
  882. #if    DEBUGM
  883. /*        Interactive debugger
  884.  
  885.         if $debug == TRUE, The interactive debugger is invoked
  886.         commands are listed out with the ? key            */
  887.  
  888. PASCAL NEAR debug(bp, eline, skipflag)
  889.  
  890. BUFFER *bp;    /* buffer to execute */
  891. char *eline;    /* text of line to debug */
  892. int *skipflag;    /* are we skipping debugging? */
  893.  
  894. {
  895.     register int oldcmd;        /* original command display flag */
  896.     register int oldinp;        /* original connamd input flag */
  897.     register int oldstatus;        /* status of last command */
  898.     register int c;            /* temp character */
  899.     register KEYTAB *key;        /* ptr to a key entry */
  900.     static char track[NSTRING] = "";/* expression to track value of */
  901.     char temp[NSTRING];        /* command or expression */
  902.  
  903. dbuild:    /* Build the information line to be presented to the user */
  904.  
  905.     strcpy(outline, "<<<");
  906.  
  907.     /* display the tracked expression */
  908.     if (track[0] != 0) {
  909.         oldstatus = cmdstatus;
  910.         docmd(track);
  911.         cmdstatus = oldstatus;
  912.         strcat(outline, "[=");
  913.         strcat(outline, gtusr("track"));
  914.         strcat(outline, "]");
  915.     }
  916.  
  917.     /* debug macro name */
  918.     strcat(outline, bp->b_bname);
  919.     strcat(outline, ":");
  920.  
  921.     /* and lastly the line */
  922.     strcat(outline, eline);
  923.     strcat(outline, ">>>");
  924.  
  925.     /* expand the %'s so mlwrite() won't interpret them */
  926.     makelit(outline);
  927.  
  928.     /* write out the debug line */
  929. dinput:    outline[term.t_ncol - 1] = 0;
  930.     mlforce(outline);
  931.     update(TRUE);
  932.  
  933.     /* and get the keystroke */
  934.     c = getkey();
  935.  
  936.     /* META key turns off debugging */
  937.     key = getbind(c);
  938.     if (key && key->k_ptr.fp == meta)
  939.         macbug = FALSE;
  940.  
  941.     else if (c == abortc) {
  942.         return(FALSE);
  943.  
  944.     } else switch (c) {
  945.  
  946.         case '?': /* list commands */
  947.             strcpy(outline, TEXT128);
  948. /*"(e)val exp, (c/x)ommand, (t)rack exp, (^G)abort, <SP>exec, <META> stop debug"*/
  949.             goto dinput;
  950.  
  951.         case 'c': /* execute statement */
  952.             oldcmd = discmd;
  953.             discmd = TRUE;
  954.             oldinp = disinp;
  955.             disinp = TRUE;
  956.             execcmd(FALSE, 1);
  957.             discmd = oldcmd;
  958.             disinp = oldinp;
  959.             goto dbuild;
  960.  
  961.         case 'x': /* execute extended command */
  962.             oldcmd = discmd;
  963.             discmd = TRUE;
  964.             oldinp = disinp;
  965.             disinp = TRUE;
  966.             oldstatus = cmdstatus;
  967.             namedcmd(FALSE, 1);
  968.             cmdstatus = oldstatus;
  969.             discmd = oldcmd;
  970.             disinp = oldinp;
  971.             goto dbuild;
  972.  
  973.         case 'e': /* evaluate expresion */
  974.             strcpy(temp, "set %track ");
  975.             oldcmd = discmd;
  976.             discmd = TRUE;
  977.             oldinp = disinp;
  978.             disinp = TRUE;
  979.             getstring("Exp: ", &temp[11], NSTRING, ctoec('\r'));
  980.             discmd = oldcmd;
  981.             disinp = oldinp;
  982.             oldstatus = cmdstatus;
  983.             docmd(temp);
  984.             cmdstatus = oldstatus;
  985.             strcpy(temp, " = [");
  986.             strcat(temp, gtusr("track"));
  987.             strcat(temp, "]");
  988.             mlforce(temp);
  989.             c = getkey();
  990.             goto dinput;
  991.  
  992.         case 't': /* track expresion */
  993.             oldcmd = discmd;
  994.             discmd = TRUE;
  995.             oldinp = disinp;
  996.             disinp = TRUE;
  997.             getstring("Exp: ", temp, NSTRING, ctoec('\r'));
  998.             discmd = oldcmd;
  999.             disinp = oldinp;
  1000.             strcpy(track, "set %track ");
  1001.             strcat(track, temp);
  1002.             goto dbuild;
  1003.  
  1004.         case 's': /* execute a function */
  1005.             *skipflag = TRUE;
  1006.             macbug = FALSE;
  1007.             break;
  1008.  
  1009.         case ' ': /* execute a statement */
  1010.             break;
  1011.  
  1012.         default: /* illegal command */
  1013.             TTbeep();
  1014.             goto dbuild;
  1015.     }
  1016.     return(TRUE);
  1017. }
  1018. #endif
  1019.  
  1020. PASCAL NEAR makelit(s)        /* expand all "%" to "%%" */
  1021.  
  1022. char *s;    /* string to expand */
  1023.  
  1024. {
  1025.     register char *sp;    /* temp for expanding string */
  1026.     register char *ep;    /* ptr to end of string to expand */
  1027.  
  1028.     sp = s;
  1029.     while (*sp)
  1030.     if (*sp++ == '%') {
  1031.         /* advance to the end */
  1032.         ep = --sp;
  1033.         while (*ep++)
  1034.             ;
  1035.         /* null terminate the string one out */
  1036.         *(ep + 1) = 0;
  1037.         /* copy backwards */
  1038.         while(ep-- > sp)
  1039.             *(ep + 1) = *ep;
  1040.  
  1041.         /* and advance sp past the new % */
  1042.         sp += 2;                    
  1043.     }
  1044. }
  1045.  
  1046. PASCAL NEAR freewhile(wp)    /* free a list of while block pointers */
  1047.  
  1048. WHBLOCK *wp;    /* head of structure to free */
  1049.  
  1050. {
  1051.     if (wp != NULL)
  1052.     {
  1053.         freewhile(wp->w_next);
  1054.         free((char *) wp);
  1055.     }
  1056. }
  1057.  
  1058. PASCAL NEAR execfile(f, n)    /* execute a series of commands in a file */
  1059.  
  1060. int f, n;    /* default flag and numeric arg to pass on to file */
  1061.  
  1062. {
  1063.     register int status;    /* return status of name query */
  1064.     char fname[NSTRING];    /* name of file to execute */
  1065.     char *fspec;        /* full file spec */
  1066.  
  1067.     if ((status = mlreply(TEXT129, fname, NSTRING -1)) != TRUE)
  1068. /*                            "File to execute: " */
  1069.         return(status);
  1070.  
  1071.     /* look up the path for the file */
  1072.     fspec = flook(fname, TRUE);
  1073.  
  1074.     /* if it isn't around */
  1075.     if (fspec == NULL) {
  1076.  
  1077.         /* try to default the extension */
  1078.         if (sindex(fname, ".") == 0) {
  1079.             strcat(fname, ".cmd");
  1080.             fspec = flook(fname, TRUE);
  1081.             if (fspec != NULL)
  1082.                 goto exec1;
  1083.         }
  1084.  
  1085.         /* complain if we are interactive */
  1086.         if (clexec == FALSE)
  1087.             mlwrite(TEXT214, fname);
  1088. /*                    "%%No such file as %s" */
  1089.         return(FALSE);
  1090.     }
  1091.  
  1092. exec1:    /* otherwise, execute it */
  1093.     while (n-- > 0)
  1094.         if ((status=dofile(fspec)) != TRUE)
  1095.             return(status);
  1096.  
  1097.     return(TRUE);
  1098. }
  1099.  
  1100. /*    dofile:    yank a file into a buffer and execute it
  1101.         if there are no errors, delete the buffer on exit */
  1102.  
  1103. PASCAL NEAR dofile(fname)
  1104.  
  1105. char *fname;    /* file name to execute */
  1106.  
  1107. {
  1108.     register BUFFER *bp;    /* buffer to place file to exeute */
  1109.     register BUFFER *cb;    /* temp to hold current buf while we read */
  1110.     register int status;    /* results of various calls */
  1111.     char bname[NBUFN];    /* name of buffer */
  1112.  
  1113.     makename(bname, fname);        /* derive the name of the buffer */
  1114.     unqname(bname);            /* make sure we don't stomp things */
  1115.     if ((bp = bfind(bname, TRUE, 0)) == NULL) /* get the needed buffer */
  1116.         return(FALSE);
  1117.  
  1118.     bp->b_mode = MDVIEW;    /* mark the buffer as read only */
  1119.     cb = curbp;        /* save the old buffer */
  1120.     curbp = bp;        /* make this one current */
  1121.     /* and try to read in the file to execute */
  1122.     if ((status = readin(fname, FALSE)) != TRUE) {
  1123.         curbp = cb;    /* restore the current buffer */
  1124.         return(status);
  1125.     }
  1126.  
  1127.     /* go execute it! */
  1128.     curbp = cb;        /* restore the current buffer */
  1129.     if ((status = dobuf(bp)) != TRUE)
  1130.         return(status);
  1131.  
  1132.     /* if not displayed, remove the now unneeded buffer and exit */
  1133.     if (bp->b_nwnd == 0)
  1134.         zotbuf(bp);
  1135.     return(TRUE);
  1136. }
  1137.  
  1138. /*    cbuf:    Execute the contents of a numbered buffer    */
  1139.  
  1140. PASCAL NEAR cbuf(f, n, bufnum)
  1141.  
  1142. int f, n;    /* default flag and numeric arg */
  1143. int bufnum;    /* number of buffer to execute */
  1144.  
  1145. {
  1146.         register BUFFER *bp;        /* ptr to buffer to execute */
  1147.         register int status;        /* status return */
  1148.     static char bufname[] = "[Macro xx]";
  1149.  
  1150.     /* make the buffer name */
  1151.     bufname[7] = '0' + (bufnum / 10);
  1152.     bufname[8] = '0' + (bufnum % 10);
  1153.  
  1154.     /* find the pointer to that buffer */
  1155.         if ((bp=bfind(bufname, FALSE, 0)) == NULL) {
  1156.             mlwrite(TEXT130);
  1157. /*                      "Macro not defined" */
  1158.                 return(FALSE);
  1159.         }
  1160.  
  1161.     /* and now execute it as asked */
  1162.     while (n-- > 0)
  1163.         if ((status = dobuf(bp)) != TRUE)
  1164.             return(status);
  1165.     return(TRUE);
  1166. }
  1167.  
  1168. PASCAL NEAR cbuf1(f, n)
  1169.  
  1170. int f, n;    /* flag and numeric argument */
  1171.  
  1172. {
  1173.     return(cbuf(f, n, 1));
  1174. }
  1175.  
  1176. PASCAL NEAR cbuf2(f, n)
  1177.  
  1178. int f, n;    /* flag and numeric argument */
  1179.  
  1180. {
  1181.     return(cbuf(f, n, 2));
  1182. }
  1183.  
  1184. PASCAL NEAR cbuf3(f, n)
  1185.  
  1186. int f, n;    /* flag and numeric argument */
  1187.  
  1188. {
  1189.     return(cbuf(f, n, 3));
  1190. }
  1191.  
  1192. PASCAL NEAR cbuf4(f, n)
  1193.  
  1194. int f, n;    /* flag and numeric argument */
  1195.  
  1196. {
  1197.     return(cbuf(f, n, 4));
  1198. }
  1199.  
  1200. PASCAL NEAR cbuf5(f, n)
  1201.  
  1202. int f, n;    /* flag and numeric argument */
  1203.  
  1204. {
  1205.     return(cbuf(f, n, 5));
  1206. }
  1207.  
  1208. PASCAL NEAR cbuf6(f, n)
  1209.  
  1210. int f, n;    /* flag and numeric argument */
  1211.  
  1212. {
  1213.     return(cbuf(f, n, 6));
  1214. }
  1215.  
  1216. PASCAL NEAR cbuf7(f, n)
  1217.  
  1218. int f, n;    /* flag and numeric argument */
  1219.  
  1220. {
  1221.     return(cbuf(f, n, 7));
  1222. }
  1223.  
  1224. PASCAL NEAR cbuf8(f, n)
  1225.  
  1226. int f, n;    /* flag and numeric argument */
  1227.  
  1228. {
  1229.     return(cbuf(f, n, 8));
  1230. }
  1231.  
  1232. PASCAL NEAR cbuf9(f, n)
  1233.  
  1234. int f, n;    /* flag and numeric argument */
  1235.  
  1236. {
  1237.     return(cbuf(f, n, 9));
  1238. }
  1239.  
  1240. PASCAL NEAR cbuf10(f, n)
  1241.  
  1242. int f, n;    /* flag and numeric argument */
  1243.  
  1244. {
  1245.     return(cbuf(f, n, 10));
  1246. }
  1247.  
  1248. PASCAL NEAR cbuf11(f, n)
  1249.  
  1250. int f, n;    /* flag and numeric argument */
  1251.  
  1252. {
  1253.     return(cbuf(f, n, 11));
  1254. }
  1255.  
  1256. PASCAL NEAR cbuf12(f, n)
  1257.  
  1258. int f, n;    /* flag and numeric argument */
  1259.  
  1260. {
  1261.     return(cbuf(f, n, 12));
  1262. }
  1263.  
  1264. PASCAL NEAR cbuf13(f, n)
  1265.  
  1266. int f, n;    /* flag and numeric argument */
  1267.  
  1268. {
  1269.     return(cbuf(f, n, 13));
  1270. }
  1271.  
  1272. PASCAL NEAR cbuf14(f, n)
  1273.  
  1274. int f, n;    /* flag and numeric argument */
  1275.  
  1276. {
  1277.     return(cbuf(f, n, 14));
  1278. }
  1279.  
  1280. PASCAL NEAR cbuf15(f, n)
  1281.  
  1282. int f, n;    /* flag and numeric argument */
  1283.  
  1284. {
  1285.     return(cbuf(f, n, 15));
  1286. }
  1287.  
  1288. PASCAL NEAR cbuf16(f, n)
  1289.  
  1290. int f, n;    /* flag and numeric argument */
  1291.  
  1292. {
  1293.     return(cbuf(f, n, 16));
  1294. }
  1295.  
  1296. PASCAL NEAR cbuf17(f, n)
  1297.  
  1298. int f, n;    /* flag and numeric argument */
  1299.  
  1300. {
  1301.     return(cbuf(f, n, 17));
  1302. }
  1303.  
  1304. PASCAL NEAR cbuf18(f, n)
  1305.  
  1306. int f, n;    /* flag and numeric argument */
  1307.  
  1308. {
  1309.     return(cbuf(f, n, 18));
  1310. }
  1311.  
  1312. PASCAL NEAR cbuf19(f, n)
  1313.  
  1314. int f, n;    /* flag and numeric argument */
  1315.  
  1316. {
  1317.     return(cbuf(f, n, 19));
  1318. }
  1319.  
  1320. PASCAL NEAR cbuf20(f, n)
  1321.  
  1322. int f, n;    /* flag and numeric argument */
  1323.  
  1324. {
  1325.     return(cbuf(f, n, 20));
  1326. }
  1327.  
  1328. PASCAL NEAR cbuf21(f, n)
  1329.  
  1330. int f, n;    /* flag and numeric argument */
  1331.  
  1332. {
  1333.     return(cbuf(f, n, 21));
  1334. }
  1335.  
  1336. PASCAL NEAR cbuf22(f, n)
  1337.  
  1338. int f, n;    /* flag and numeric argument */
  1339.  
  1340. {
  1341.     return(cbuf(f, n, 22));
  1342. }
  1343.  
  1344. PASCAL NEAR cbuf23(f, n)
  1345.  
  1346. int f, n;    /* flag and numeric argument */
  1347.  
  1348. {
  1349.     return(cbuf(f, n, 23));
  1350. }
  1351.  
  1352. PASCAL NEAR cbuf24(f, n)
  1353.  
  1354. int f, n;    /* flag and numeric argument */
  1355.  
  1356. {
  1357.     return(cbuf(f, n, 24));
  1358. }
  1359.  
  1360. PASCAL NEAR cbuf25(f, n)
  1361.  
  1362. int f, n;    /* flag and numeric argument */
  1363.  
  1364. {
  1365.     return(cbuf(f, n, 25));
  1366. }
  1367.  
  1368. PASCAL NEAR cbuf26(f, n)
  1369.  
  1370. int f, n;    /* flag and numeric argument */
  1371.  
  1372. {
  1373.     return(cbuf(f, n, 26));
  1374. }
  1375.  
  1376. PASCAL NEAR cbuf27(f, n)
  1377.  
  1378. int f, n;    /* flag and numeric argument */
  1379.  
  1380. {
  1381.     return(cbuf(f, n, 27));
  1382. }
  1383.  
  1384. PASCAL NEAR cbuf28(f, n)
  1385.  
  1386. int f, n;    /* flag and numeric argument */
  1387.  
  1388. {
  1389.     return(cbuf(f, n, 28));
  1390. }
  1391.  
  1392. PASCAL NEAR cbuf29(f, n)
  1393.  
  1394. int f, n;    /* flag and numeric argument */
  1395.  
  1396. {
  1397.     return(cbuf(f, n, 29));
  1398. }
  1399.  
  1400. PASCAL NEAR cbuf30(f, n)
  1401.  
  1402. int f, n;    /* flag and numeric argument */
  1403.  
  1404. {
  1405.     return(cbuf(f, n, 30));
  1406. }
  1407.  
  1408. PASCAL NEAR cbuf31(f, n)
  1409.  
  1410. int f, n;    /* flag and numeric argument */
  1411.  
  1412. {
  1413.     return(cbuf(f, n, 31));
  1414. }
  1415.  
  1416. PASCAL NEAR cbuf32(f, n)
  1417.  
  1418. int f, n;    /* flag and numeric argument */
  1419.  
  1420. {
  1421.     return(cbuf(f, n, 32));
  1422. }
  1423.  
  1424. PASCAL NEAR cbuf33(f, n)
  1425.  
  1426. int f, n;    /* flag and numeric argument */
  1427.  
  1428. {
  1429.     return(cbuf(f, n, 33));
  1430. }
  1431.  
  1432. PASCAL NEAR cbuf34(f, n)
  1433.  
  1434. int f, n;    /* flag and numeric argument */
  1435.  
  1436. {
  1437.     return(cbuf(f, n, 34));
  1438. }
  1439.  
  1440. PASCAL NEAR cbuf35(f, n)
  1441.  
  1442. int f, n;    /* flag and numeric argument */
  1443.  
  1444. {
  1445.     return(cbuf(f, n, 35));
  1446. }
  1447.  
  1448. PASCAL NEAR cbuf36(f, n)
  1449.  
  1450. int f, n;    /* flag and numeric argument */
  1451.  
  1452. {
  1453.     return(cbuf(f, n, 36));
  1454. }
  1455.  
  1456. PASCAL NEAR cbuf37(f, n)
  1457.  
  1458. int f, n;    /* flag and numeric argument */
  1459.  
  1460. {
  1461.     return(cbuf(f, n, 37));
  1462. }
  1463.  
  1464. PASCAL NEAR cbuf38(f, n)
  1465.  
  1466. int f, n;    /* flag and numeric argument */
  1467.  
  1468. {
  1469.     return(cbuf(f, n, 38));
  1470. }
  1471.  
  1472. PASCAL NEAR cbuf39(f, n)
  1473.  
  1474. int f, n;    /* flag and numeric argument */
  1475.  
  1476. {
  1477.     return(cbuf(f, n, 39));
  1478. }
  1479.  
  1480. PASCAL NEAR cbuf40(f, n)
  1481.  
  1482. int f, n;    /* flag and numeric argument */
  1483.  
  1484. {
  1485.     return(cbuf(f, n, 40));
  1486. }
  1487.  
  1488.  
  1489.