home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ucb_logoppc / source / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-20  |  17.2 KB  |  665 lines

  1. /*
  2.  *      parse.c         logo parser module              dvb
  3.  *
  4.  * Copyright (C) 1993 by the Regents of the University of California
  5.  *
  6.  *      This program is free software; you can redistribute it and/or modify
  7.  *      it under the terms of the GNU General Public License as published by
  8.  *      the Free Software Foundation; either version 2 of the License, or
  9.  *      (at your option) any later version.
  10.  *
  11.  *      This program is distributed in the hope that it will be useful,
  12.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *      GNU General Public License for more details.
  15.  *
  16.  *      You should have received a copy of the GNU General Public License
  17.  *      along with this program; if not, write to the Free Software
  18.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  */
  21.  
  22. #ifdef WIN32
  23. #include <windows.h>
  24. #endif
  25.  
  26. #include "logo.h"
  27. #include "globals.h"
  28.  
  29. #ifdef HAVE_TERMIO_H
  30. #include <termio.h>
  31. #else
  32. #ifdef HAVE_SGTTY_H
  33. #include <sgtty.h>
  34. #endif
  35. #endif
  36.  
  37. #include <ctype.h>
  38.  
  39. #ifdef ibm
  40. #ifndef _MSC_VER
  41. #include <bios.h>
  42. extern int getch(void);
  43. #endif /* _MSC_VER */
  44. #endif
  45. #ifdef __ZTC__
  46. #include <disp.h>
  47. #endif
  48.  
  49. #if defined(__PPC__) && defined(AMIGA)
  50.  
  51. #define __USE_SYSBASE
  52. #include <proto/exec.h>
  53. #include <proto/dos.h>
  54. #include <powerup/ppclib/interface.h>
  55. #include <powerup/gcclib/powerup_protos.h>
  56.  
  57. #define AllocVec(n, f) PPCAllocVec(n, f)
  58. #define FreeVec(b)     PPCFreeVec(b)
  59.  
  60. #endif
  61.  
  62. FILE *readstream = stdin;
  63. FILE *writestream = stdout;
  64. FILE *loadstream = stdin;
  65. FILE *dribblestream = NULL;
  66. int input_blocking = 0;
  67. NODE *deepend_proc_name = NIL;
  68.  
  69. #ifdef AMIGA
  70. int rd_getc(FILE *strm)
  71. {
  72.    int c;
  73.  
  74.    /*
  75.       CTRL-C and CTRL-D are only used to stop and pause,
  76.       so they shouldn't ever reach the reader functions.
  77.    */
  78.    if (strm==stdin && console!=NULL)
  79.       do
  80.          c = FGetC(console);
  81.       while (c=='\003' || c=='\004');
  82.    else
  83.       c = getc(strm);
  84.    if (strm == stdin && c != EOF)
  85.       update_coords(c);
  86.    return(c);
  87. }
  88. #else
  89.  
  90. int rd_getc(FILE *strm) {
  91.     int c;
  92. #ifdef WIN32
  93.     MSG msg;
  94. #endif
  95.  
  96. #ifndef WIN32 /* skip this section ... */
  97. #ifdef __ZTC__
  98.     if (strm == stdin) zflush();
  99.     c = ztc_getc(strm);
  100. #else
  101.     c = getc(strm);
  102. #endif
  103.     if (strm == stdin && c != EOF) update_coords(c);
  104. #ifdef ibm
  105.     if (c == 17 && interactive && strm==stdin) { /* control-q */
  106.    to_pending = 0;
  107.    err_logo(STOP_ERROR,NIL);
  108.     }
  109.     if (c == 23 && interactive && strm==stdin) { /* control-w */
  110. #ifndef __ZTC__
  111.    getc(strm); /* eat up the return */
  112. #endif
  113.  
  114. #if defined(__ZTC__) || defined(WIN32)
  115.    logo_pause(0);
  116. #else
  117.    logo_pause();
  118. #endif
  119.  
  120.    return(rd_getc(strm));
  121.     }
  122. #endif
  123. #else /* WIN32 */
  124.     if (strm == stdin) {
  125.    if (!line_avail) {
  126.        win32_text_cursor();
  127.        while (GetMessage(&msg, NULL, 0, 0)) {
  128.       TranslateMessage(&msg);
  129.       DispatchMessage(&msg);
  130.       if (line_avail)
  131.           break;
  132.       }
  133.        }
  134.       c = read_line[read_index++];
  135.       if (c == 17 && interactive && strm==stdin) { /* control-q */
  136.    to_pending = 0;
  137.    err_logo(STOP_ERROR,NIL);
  138.    line_avail = 0;
  139.    return('\n');
  140.     }
  141.     if (c == 23 && interactive && strm==stdin) { /* control-w */
  142.    line_avail = 0;
  143.    logo_pause(0);
  144.    return(rd_getc(strm));
  145.     }
  146.       if (c == '\n')
  147.    line_avail = 0;
  148.     }
  149.     else /* reading from a file */
  150.       c = getc(strm);
  151. #endif /* WIN32 */
  152.  
  153. #ifdef ecma
  154.     return(ecma_clear(c));
  155. #else
  156.     return(c);
  157. #endif
  158. }
  159.  
  160. #endif /* AMIGA */
  161.  
  162.  
  163. void rd_print_prompt(char *str) {
  164. #ifdef ibm
  165. #if defined(__ZTC__) || defined(WIN32)
  166.     if (in_graphics_mode && !in_splitscreen)
  167. #else
  168. #ifndef _MSC_VER
  169.     if (in_graphics_mode && ibm_screen_top == 0)
  170. #endif /* _MSC_VER */
  171. #endif
  172.    lsplitscreen(NIL);
  173. #endif
  174.     ndprintf(stdout,"%t",str);
  175. #if defined(__ZTC__) && !defined(WIN32) /* sowings */
  176.     zflush();
  177. #endif
  178. #ifdef AMIGA
  179.     if (console)
  180.         Flush(console);
  181. #endif
  182. }
  183.  
  184. #if defined(__ZTC__) && !defined(WIN32) /* sowings */
  185. void zrd_print_prompt(char *str) {
  186.     newline_bugfix();
  187.     rd_print_prompt(str);
  188. }
  189. #else
  190. #define zrd_print_prompt rd_print_prompt
  191. #endif
  192.  
  193. #define into_line(chr) {if (phys_line >= p_end) { \
  194.             p_len += MAX_PHYS_LINE; \
  195.             p_pos = phys_line - p_line; \
  196.             p_line = realloc(p_line, p_len); \
  197.             p_end = &p_line[p_len-1]; \
  198.             phys_line = &p_line[p_pos]; \
  199.              } \
  200.              *phys_line++ = (chr);}
  201.  
  202. char *p_line = 0, *p_end;
  203. int p_len = MAX_PHYS_LINE;
  204.  
  205. NODE *reader(FILE *strm, char *prompt) {
  206.     int c = 0, dribbling, vbar = 0, paren = 0;
  207.     int bracket = 0, brace = 0, p_pos, contin=1;
  208.     static char ender[] = "\nEND\n";
  209.     char *phys_line, *lookfor = ender;
  210.     NODETYPES this_type = STRING;
  211.     NODE *ret;
  212.  
  213. #ifdef AMIGA
  214.    if (strm==stdin)
  215.       SetMode(console,0);  /* turn buffering on */
  216. #endif
  217.    if (!strcmp(prompt, "RW")) {  /* called by readword */
  218.       prompt = "";
  219.       contin = 0;
  220.    }
  221.     charmode_off();
  222. #ifdef WIN32
  223.     dribbling = 0;
  224. #else
  225.     dribbling = (dribblestream != NULL && strm == stdin);
  226. #endif
  227.     if (p_line == 0) {
  228.       p_line = malloc(MAX_PHYS_LINE);
  229.    if (p_line == NULL) {
  230.        err_logo(OUT_OF_MEM, NIL);
  231.           return UNBOUND;
  232.    }
  233.       p_end = &p_line[MAX_PHYS_LINE-1];
  234.     }
  235.     phys_line = p_line;
  236.     if (strm == stdin && *prompt) {
  237.    if (interactive) {
  238.      rd_print_prompt(prompt);
  239. #ifdef WIN32
  240.      win32_update_text();
  241. #endif
  242.    }
  243.     }
  244.     if (strm == stdin) {
  245.    input_blocking++;
  246.    erract_errtype = FATAL;
  247.     }
  248.  
  249. #ifndef TIOCSTI
  250.     if (!setjmp(iblk_buf)) {
  251. #endif
  252.     c = rd_getc(strm);
  253.     while (c != EOF && (vbar || paren || bracket || brace || c != '\n')) {
  254.    if (dribbling) rd_putc(c, dribblestream);
  255.    if (c == '\\' && (c = rd_getc(strm)) != EOF) {
  256.        if (dribbling) rd_putc(c, dribblestream);
  257.        c = setparity(c);
  258.        this_type = BACKSLASH_STRING;
  259.        if (c == setparity('\n') && strm == stdin) {
  260.       if (interactive) zrd_print_prompt("\\ ");
  261.        }
  262.    }
  263.    if (c != EOF) into_line(c);
  264.       if (*prompt && (c&0137) == *lookfor) {
  265.          lookfor++;
  266.          if (*lookfor == 0) {
  267.             err_logo(DEEPEND, deepend_proc_name);
  268.             break;
  269.          }
  270.       } else lookfor = ender;
  271.    if (c == '|') {
  272.        vbar = !vbar;
  273.        this_type = VBAR_STRING;
  274.    } else if (contin && !vbar) {
  275.       if (c == '(') paren++;
  276.       else if (paren && c == ')') paren--;
  277.       else if (c == '[') bracket++;
  278.       else if (bracket && c == ']') bracket--;
  279.       else if (c == '{') brace++;
  280.       else if (brace && c == '}') brace--;
  281.    }
  282.  
  283.    if (this_type == STRING && strchr(special_chars, c))
  284.        this_type = VBAR_STRING;
  285.    if (/* (vbar || paren ...) && */ c == '\n') {
  286.        if (strm == stdin) {
  287.       if (interactive) zrd_print_prompt(vbar ? "| " : "~ ");
  288.        }
  289.    }
  290.    while (!vbar && c == '~' && (c = rd_getc(strm)) != EOF) {
  291.        while (c == ' ' || c == '\t')
  292.       c = rd_getc(strm);
  293.        if (dribbling) rd_putc(c, dribblestream);
  294.        into_line(c);
  295.        if (c == '\n' && strm == stdin) {
  296.       if (interactive) zrd_print_prompt("~ ");
  297.        }
  298.    }
  299.    if (c != EOF) c = rd_getc(strm);
  300.     }
  301. #ifndef TIOCSTI
  302.     }
  303. #endif
  304.     *phys_line = '\0';
  305.     input_blocking = 0;
  306. #if defined(__ZTC__) && !defined(WIN32) /* sowings */
  307.     fix_cursor();
  308.     if (interactive && strm == stdin) newline_bugfix();
  309. #endif
  310.     if (dribbling)
  311.    rd_putc('\n', dribblestream);
  312.     if (c == EOF && strm == stdin) {
  313.    if (interactive) clearerr(stdin);
  314.    rd_print_prompt("\n");
  315.     }
  316. #ifdef AMIGA
  317.    if (strm==stdin)
  318.       SetMode(console,1);  /* turn buffering off */
  319. #endif
  320.     if (phys_line == p_line) return(Null_Word); /* so emptyp works */
  321.     ret = make_strnode(p_line, (struct string_block *)NULL, (int)strlen(p_line),
  322.              this_type, strnzcpy);
  323.     return(ret);
  324. }
  325.  
  326. NODE *list_to_array(NODE *list) {
  327.     NODE *np = list, *result;
  328.     int len = 0, i;
  329.  
  330.     for (; np; np = cdr(np)) len++;
  331.  
  332.     result = make_array(len);
  333.     setarrorg(result,1);
  334.  
  335.     for (i = 0, np = list; np; np = cdr(np))
  336.    (getarrptr(result))[i++] = car(np);
  337.  
  338.     return(result);
  339. }
  340.  
  341. #define parens(ch)      (ch == '(' || ch == ')' || ch == ';')
  342. #define infixs(ch)      (ch == '*' || ch == '/' || ch == '+' || ch == '-' || ch == '=' || ch == '<' || ch == '>')
  343. #define white_space(ch) (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0')
  344.  
  345. NODE *parser_iterate(char **inln, char *inlimit, struct string_block *inhead,
  346.            BOOLEAN semi, int endchar) {
  347.     char ch, *wptr = NULL;
  348.     static char terminate = '\0';   /* KLUDGE */
  349.     NODE *outline = NIL, *lastnode = NIL, *tnode = NIL;
  350.     int windex = 0, vbar = 0;
  351.     NODETYPES this_type = STRING;
  352.     BOOLEAN broken = FALSE;
  353.  
  354.     do {
  355.    /* get the current character and increase pointer */
  356.    ch = **inln;
  357.    if (!vbar && windex == 0) wptr = *inln;
  358.    if (++(*inln) >= inlimit) *inln = &terminate;
  359.  
  360.    /* skip through comments and line continuations */
  361.    while (!vbar && ((semi && ch == ';') ||
  362. #ifdef WIN32
  363.       (ch == '~' && (**inln == 012 || **inln == 015)))) {
  364.        while (ch == '~' && (**inln == 012 || **inln == 015)) {
  365. #else
  366.       (ch == '~' && **inln == '\n'))) {
  367.        while (ch == '~' && **inln == '\n') {
  368. #endif
  369.       if (++(*inln) >= inlimit) *inln = &terminate;
  370.       ch = **inln;
  371.       if (windex == 0) wptr = *inln;
  372.       else {
  373.           if (**inln == ']' || **inln == '[' ||
  374.                    **inln == '{' || **inln == '}') {
  375.          ch = ' ';
  376.          break;
  377.           } else {
  378.          broken = TRUE;
  379.           }
  380.       }
  381.       if (++(*inln) >= inlimit) *inln = &terminate;
  382.        }
  383.  
  384.        if (semi && ch == ';') {
  385. #ifdef WIN32
  386.       if (**inln != 012 && **inln != 015)
  387. #else
  388.       if (**inln != '\n')
  389. #endif
  390.       do {
  391.           ch = **inln;
  392.           if (windex == 0) wptr = *inln;
  393.           else broken = TRUE;
  394.           if (++(*inln) >= inlimit) *inln = &terminate;
  395.       }
  396. #ifdef WIN32
  397.       while (ch != '\0' && ch != '~' && **inln != 012 && **inln != 015);
  398. #else /* !Win32 */
  399.       while (ch != '\0' && ch != '~' && **inln != '\n');
  400. #endif
  401.       if (ch != '\0' && ch != '~') ch = '\n';
  402.        }
  403.    }
  404.  
  405.    /* flag that this word will be of BACKSLASH_STRING type */
  406.    if (getparity(ch)) this_type = BACKSLASH_STRING;
  407.  
  408.    if (ch == '|') {
  409.        vbar = !vbar;
  410.        this_type = VBAR_STRING;
  411.        broken = TRUE; /* so we'll copy the chars */
  412.    }
  413.  
  414.    else if (vbar || (!white_space(ch) && ch != ']' &&
  415.           ch != '{' && ch != '}' && ch != '['))
  416.        windex++;
  417.  
  418.    if (vbar) continue;
  419.  
  420.    else if (ch == endchar) break;
  421.  
  422.    else if (ch == ']') err_logo(UNEXPECTED_BRACKET, NIL);
  423.    else if (ch == '}') err_logo(UNEXPECTED_BRACE, NIL);
  424.  
  425.    /* if this is a '[', parse a new list */
  426.    else if (ch == '[') {
  427.        tnode = cons(parser_iterate(inln,inlimit,inhead,semi,']'), NIL);
  428.        if (**inln == '\0') ch = '\0';
  429.    }
  430.  
  431.    else if (ch == '{') {
  432.        tnode = cons(list_to_array
  433.           (parser_iterate(inln,inlimit,inhead,semi,'}')), NIL);
  434.        if (**inln == '@') {
  435.       int i = 0, sign = 1;
  436.  
  437.       (*inln)++;
  438.       if (**inln == '-') {
  439.           sign = -1;
  440.           (*inln)++;
  441.       }
  442.       while ((ch = **inln) >= '0' && ch <= '9') {
  443.           i = (i*10) + ch - '0';
  444.           (*inln)++;
  445.       }
  446.       setarrorg(car(tnode),sign*i);
  447.        }
  448.        if (**inln == '\0') ch = '\0';
  449.    }
  450.  
  451. /* if this character or the next one will terminate string, make the word */
  452.    else if (white_space(ch) || **inln == ']' || **inln == '[' ||
  453.              **inln == '{' || **inln == '}') {
  454.       if (windex > 0) {
  455.           if (broken == FALSE)
  456.           tnode = cons(make_strnode(wptr, inhead, windex,
  457.                      this_type, strnzcpy),
  458.                   NIL);
  459.           else {
  460.           tnode = cons(make_strnode(wptr,
  461.              (struct string_block *)NULL, windex,
  462.              this_type, (semi ? mend_strnzcpy : mend_nosemi)),
  463.              NIL);
  464.           broken = FALSE;
  465.           }
  466.           this_type = STRING;
  467.           windex = 0;
  468.       }
  469.    }
  470.  
  471.    /* put the word onto the end of the return list */
  472.    if (tnode != NIL) {
  473.        if (outline == NIL) outline = tnode;
  474.        else setcdr(lastnode, tnode);
  475.        lastnode = tnode;
  476.        tnode = NIL;
  477.    }
  478.     } while (ch);
  479.     return(outline);
  480. }
  481.  
  482. NODE *parser(NODE *nd, BOOLEAN semi) {
  483.     NODE *rtn;
  484.     int slen;
  485.     char *lnsav;
  486.  
  487.     rtn = cnv_node_to_strnode(nd);
  488.     slen = getstrlen(rtn);
  489.     lnsav = getstrptr(rtn);
  490.     rtn = parser_iterate(&lnsav,lnsav + slen,getstrhead(rtn),semi,-1);
  491.     return(rtn);
  492. }
  493.  
  494. NODE *lparse(NODE *args) {
  495.     NODE *arg, *val = UNBOUND;
  496.  
  497.     arg = string_arg(args);
  498.     if (NOT_THROWING) {
  499.    val = parser(arg, FALSE);
  500.     }
  501.     return(val);
  502. }
  503.  
  504. NODE *runparse_node(NODE *nd, NODE **ndsptr) {
  505.     NODE *outline = NIL, *tnode = NIL, *lastnode = NIL, *snd;
  506.     char *wptr, *tptr;
  507.     struct string_block *whead;
  508.     int wlen, wcnt, tcnt, isnumb, gotdot;
  509.     NODETYPES wtyp;
  510.     BOOLEAN monadic_minus = FALSE;
  511.  
  512.     if (nd == Minus_Tight) return cons(nd, NIL);
  513.     snd = cnv_node_to_strnode(nd);
  514.     wptr = getstrptr(snd);
  515.     wlen = getstrlen(snd);
  516.     wtyp = nodetype(snd);
  517.     wcnt = 0;
  518.     whead = getstrhead(snd);
  519.  
  520.     while (wcnt < wlen) {
  521.    if (*wptr == ';') {
  522.        *ndsptr = NIL;
  523.        break;
  524.    }
  525.    if (*wptr == '"') {
  526.        tcnt = 0;
  527.        tptr = ++wptr;
  528.        wcnt++;
  529.        while (wcnt < wlen && !parens(*wptr)) {
  530.       if (wtyp == BACKSLASH_STRING && getparity(*wptr))
  531.           wtyp = PUNBOUND;    /* flag for "\( case */
  532.       wptr++, wcnt++, tcnt++;
  533.        }
  534.        if (wtyp == PUNBOUND) {
  535.       wtyp = BACKSLASH_STRING;
  536.       tnode = cons(make_quote(intern(make_strnode(tptr, NULL,
  537.                tcnt, wtyp, noparity_strnzcpy))), NIL);
  538.        } else
  539.       tnode = cons(make_quote(intern(make_strnode(tptr, whead, tcnt,
  540.                     wtyp, strnzcpy))), NIL);
  541.    } else if (*wptr == ':') {
  542.        tcnt = 0;
  543.        tptr = ++wptr;
  544.        wcnt++;
  545.        while (wcnt < wlen && !parens(*wptr) && !infixs(*wptr))
  546.       wptr++, wcnt++, tcnt++;
  547.        tnode = cons(make_colon(intern(make_strnode(tptr, whead, tcnt,
  548.                 wtyp, strnzcpy))), NIL);
  549.    } else if (wcnt == 0 && *wptr == '-' && monadic_minus == FALSE &&
  550.          wcnt+1 < wlen && !white_space(*(wptr+1))) {
  551.    /* minus sign with space before and no space after is unary */
  552.        tnode = cons(make_intnode((FIXNUM)0), NIL);
  553.        monadic_minus = TRUE;
  554.    } else if (parens(*wptr) || infixs(*wptr)) {
  555.        if (monadic_minus)
  556.       tnode = cons(Minus_Tight, NIL);
  557.        else
  558.       tnode = cons(intern(make_strnode(wptr, whead, 1,
  559.                    STRING, strnzcpy)), NIL);
  560.        monadic_minus = FALSE;
  561.        wptr++, wcnt++;
  562.    } else {
  563.        tcnt = 0;
  564.        tptr = wptr;
  565.        /* isnumb 4 means nothing yet;
  566.        * 0 means digits so far, 1 means just saw
  567.         * 'e' so minus can be next, 2 means no longer
  568.         * eligible even if an 'e' comes along */
  569.        isnumb = 4;
  570.        gotdot = 0;
  571.        if (*wptr == '?') {
  572.       isnumb = 3; /* turn ?5 to (? 5) */
  573.       wptr++, wcnt++, tcnt++;
  574.        }
  575.        while (wcnt < wlen && !parens(*wptr) &&
  576.          (!infixs(*wptr) || (isnumb == 1 && (*wptr == '-' || *wptr == '+')))) {
  577.       if (isnumb == 4 && isdigit(*wptr)) isnumb = 0;
  578.       if (isnumb == 0 && tcnt > 0 && (*wptr == 'e' || *wptr == 'E'))
  579.           isnumb = 1;
  580.       else if (!(isdigit(*wptr) || (!gotdot && *wptr == '.')) || isnumb == 1)
  581.           isnumb = 2;
  582.       if (*wptr == '.') gotdot++;
  583.       wptr++, wcnt++, tcnt++;
  584.        }
  585.        if (isnumb == 3 && tcnt > 1) {    /* ?5 syntax */
  586.       NODE *qmtnode;
  587.  
  588.       qmtnode = cons_list(0, Left_Paren, Query,
  589.                 cnv_node_to_numnode
  590.                (make_strnode(tptr+1, whead,
  591.                         tcnt-1, wtyp, strnzcpy)),
  592.                 END_OF_LIST);
  593.       if (outline == NIL) {
  594.           outline = qmtnode;
  595.       } else {
  596.           setcdr(lastnode, qmtnode);
  597.       }
  598.       lastnode = cddr(qmtnode);
  599.       tnode = cons(Right_Paren, NIL);
  600.        } else if (isnumb < 2 && tcnt > 0) {
  601.       tnode = cons(cnv_node_to_numnode(make_strnode(tptr, whead, tcnt,
  602.                            wtyp, strnzcpy)),
  603.               NIL);
  604.        } else
  605.       tnode = cons(intern(make_strnode(tptr, whead, tcnt,
  606.                    wtyp, strnzcpy)),
  607.               NIL);
  608.    }
  609.  
  610.    if (outline == NIL) outline = tnode;
  611.    else setcdr(lastnode, tnode);
  612.    lastnode = tnode;
  613.     }
  614.     return(outline);
  615. }
  616.  
  617. NODE *runparse(NODE *ndlist) {
  618.     NODE *curnd = NIL, *outline = NIL, *tnode = NIL, *lastnode = NIL;
  619.  
  620.     if (nodetype(ndlist) == RUN_PARSE)
  621.       return parsed__runparse(ndlist);
  622.    if (!is_list(ndlist)) {
  623.       err_logo(BAD_DATA_UNREC, ndlist);
  624.       return(NIL);
  625.    }
  626.     while (ndlist != NIL) {
  627.    curnd = car(ndlist);
  628.    ndlist = cdr(ndlist);
  629.    if (!is_word(curnd))
  630.        tnode = cons(curnd, NIL);
  631.    else {
  632.        if (!numberp(curnd))
  633.       tnode = runparse_node(curnd, &ndlist);
  634.        else
  635.       tnode = cons(cnv_node_to_numnode(curnd), NIL);
  636.    }
  637.    if (tnode != NIL) {
  638.        if (outline == NIL) outline = tnode;
  639.        else setcdr(lastnode, tnode);
  640.        lastnode = tnode;
  641.        while (cdr(lastnode) != NIL) {
  642.       lastnode = cdr(lastnode);
  643.       if (check_throwing) break;
  644.        }
  645.    }
  646.    if (check_throwing) break;
  647.     }
  648.     return(outline);
  649. }
  650.  
  651. NODE *lrunparse(NODE *args) {
  652.     NODE *arg;
  653.  
  654.     arg = car(args);
  655.     while (nodetype(arg) == ARRAY && NOT_THROWING) {
  656.    setcar(args, err_logo(BAD_DATA, arg));
  657.    arg = car(args);
  658.     }
  659.     if (NOT_THROWING && !aggregate(arg))
  660.    arg = parser(arg, TRUE);
  661.     if (NOT_THROWING)
  662.    return runparse(arg);
  663.     return UNBOUND;
  664. }
  665.