home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1997: The Complete Utilities Toolkit / macworld-complete-utilities-1997.iso / Programming / Bob 1.5 / Bobcom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-02  |  33.1 KB  |  1,543 lines  |  [TEXT/????]

  1. /* bobcom.c - the bytecode compiler */
  2. /*
  3.     Copyright (c) 1991, by David Michael Betz
  4.     All rights reserved
  5. */
  6.  
  7. #include <setjmp.h>
  8. #include "bob.h"
  9. #include "bobcom.h"
  10.  
  11. /* partial value structure */
  12. typedef struct pvalue {
  13. #ifdef __STDC__
  14.   int (*fcn)(int,int);
  15. #else
  16.   int (*fcn)();
  17. #endif
  18.   int val;
  19. } PVAL;
  20.  
  21. /* variable access function codes */
  22. #define LOAD    1
  23. #define STORE    2
  24. #define PUSH    3
  25. #define DUP    4
  26.  
  27. /* global variables */
  28. int decode=0;         /* flag for decoding functions */
  29.  
  30. /* local variables */
  31. static ARGUMENT *arguments;    /* argument list */
  32. static ARGUMENT *temporaries;    /* temporary variable list */
  33. static LITERAL *literals;    /* literal list */
  34. static VALUE methodclass;    /* class of the current method */
  35. static unsigned char *cbuff;    /* code buffer */
  36. static int cptr;        /* code pointer */
  37.  
  38. /* break/continue stacks */
  39. #define SSIZE    10
  40. static int bstack[SSIZE],*bsp;
  41. static int cstack[SSIZE],*csp;
  42.  
  43. /* external variables */
  44. extern jmp_buf error_trap;    /* trap for compile errors */
  45. extern VALUE symbols;    /* symbol table */
  46. extern VALUE classes;    /* class table */
  47. extern VALUE *sp;    /* stack pointer */
  48. extern int t_value;    /* token value */
  49. extern char t_token[];    /* token string */
  50.  
  51. /* forward declarations */
  52. #ifdef __STDC__
  53. static void do_class(void);
  54. static DICT_ENTRY *findmember(CLASS *class,char *name);
  55. static DICT_ENTRY *rfindmember(CLASS *class,char *name);
  56. static void do_function(char *name);
  57. static void do_regular_function(char *name);
  58. static void do_member_function(VALUE *class);
  59. static VECTOR *do_code(char *name,VALUE *class);
  60. static CLASS *get_class(char *name);
  61. static void do_statement(void);
  62. static void do_if(void);
  63. static int *addbreak(int lbl);
  64. static int rembreak(int *old,int lbl);
  65. static int *addcontinue(int lbl);
  66. static int remcontinue(int *old);
  67. static void do_while(void);
  68. static void do_dowhile(void);
  69. static void do_for(void);
  70. static void do_break(void);
  71. static void do_continue(void);
  72. static void do_block(void);
  73. static void do_return(void);
  74. static void do_test(void);
  75. static void do_expr(void);
  76. static int rvalue(PVAL *pv);
  77. static int chklvalue(PVAL *pv);
  78. static void do_expr1(PVAL *pv);
  79. static void do_expr2(PVAL *pv);
  80. static void do_assignment(PVAL *pv,int op);
  81. static void do_expr3(PVAL *pv);
  82. static void do_expr4(PVAL *pv);
  83. static void do_expr5(PVAL *pv);
  84. static void do_expr6(PVAL *pv);
  85. static void do_expr7(PVAL *pv);
  86. static void do_expr8(PVAL *pv);
  87. static void do_expr9(PVAL *pv);
  88. static void do_expr10(PVAL *pv);
  89. static void do_expr11(PVAL *pv);
  90. static void do_expr12(PVAL *pv);
  91. static void do_expr13(PVAL *pv);
  92. static void do_expr14(PVAL *pv);
  93. static void do_preincrement(PVAL *pv,int op);
  94. static void do_postincrement(PVAL *pv,int op);
  95. static void do_new(PVAL *pv);
  96. static void do_expr15(PVAL *pv);
  97. static void do_primary(PVAL *pv);
  98. static void do_call(PVAL *pv);
  99. static void do_send(char *selector,PVAL *pv);
  100. static void do_index(PVAL *pv);
  101. static int get_id_list(ARGUMENT **list,char *term);
  102. static int addargument(ARGUMENT **list,char *name);
  103. static int freelist(ARGUMENT **plist);
  104. static int findarg(char *name);
  105. static int findtmp(char *name);
  106. static DICT_ENTRY *finddatamember(char *name);
  107. static int addliteral(LITERAL **list,LITERAL **pval);
  108. static int freeliterals(LITERAL **plist);
  109. static int frequire(int rtkn);
  110. static int require(int tkn,int rtkn);
  111. static void do_lit_integer(long n);
  112. static void do_lit_string(char *str);
  113. static int make_lit_string(char *str);
  114. static int make_lit_variable(DICT_ENTRY *sym);
  115. static int findvariable(char *id,PVAL *pv);
  116. static int findclassvariable(CLASS *class,char *name,PVAL *pv);
  117. static int code_argument(int fcn,int n);
  118. static int code_temporary(int fcn,int n);
  119. static int code_member(int fcn,int n);
  120. static int code_variable(int fcn,int n);
  121. static int code_index(int fcn,int n);
  122. static int code_literal(int n);
  123. static int putcbyte(int b);
  124. static int putcword(int w);
  125. static int fixup(int chn,int val);
  126. static char *copystring(char *str);
  127. static char *getmemory(int size);
  128. #else
  129. CLASS *get_class();
  130. VECTOR *do_code();
  131. char *copystring();
  132. char *getmemory();
  133. #endif
  134.  
  135. /* init_compiler - initialize the compiler */
  136. int init_compiler()
  137. {
  138. /*  char *calloc(); */
  139.     literals = NULL;
  140.     set_nil(&methodclass);
  141.     return ((cbuff = (unsigned char *)calloc(1,CMAX)) != NULL);
  142. }
  143.  
  144. /* mark_compiler - mark compiler variables */
  145. void mark_compiler()
  146. {
  147.     LITERAL *lit;
  148.     if (cbuff) {
  149.     for (lit = literals; lit != NULL; lit = lit->lit_next)
  150.         mark(&lit->lit_value);
  151.     mark(&methodclass);
  152.     }
  153. }
  154.  
  155. /* compile_definitions - compile class or function definitions */
  156. int compile_definitions(getcf,getcd)
  157.   int (*getcf)(); void *getcd;
  158. {
  159.     char name[TKNSIZE+1];
  160.     int tkn,i;
  161.  
  162.     /* trap errors */
  163.     if (setjmp(error_trap))
  164.     return (FALSE);
  165.  
  166.     /* initialize */
  167.     init_scanner(getcf,getcd);
  168.     bsp = &bstack[-1];
  169.     csp = &cstack[-1];
  170.  
  171.     /* process statements until end of file */
  172.     while ((tkn = token()) != T_EOF) {
  173.     switch (tkn) {
  174.     case T_IDENTIFIER:
  175.         strcpy(name,t_token);
  176.         do_function(name);
  177.         break;
  178.     case T_CLASS:
  179.         do_class();
  180.         break;
  181.     default:
  182.         parse_error("Expecting a declaration");
  183.         break;
  184.     }
  185.     }
  186.     return (TRUE);
  187. }
  188.  
  189. /* do_class - handle class declarations */
  190. static void do_class()
  191. {
  192.     ARGUMENT *mvars,*smvars,*fargs,**table,*p;
  193.     char cname[TKNSIZE+1],id[TKNSIZE+1];
  194.     DICT_ENTRY *entry;
  195.     int type,tkn,i;
  196.  
  197.     /* initialize */
  198.     mvars = smvars = fargs = NULL;
  199.     check(1);
  200.     
  201.     /* get the class name */
  202.     frequire(T_IDENTIFIER);
  203.     strcpy(cname,t_token);
  204.     
  205.     /* get the optional base class */
  206.     if ((tkn = token()) == ':') {
  207.     frequire(T_IDENTIFIER);
  208.     push_class(get_class(t_token));
  209.     info("Class '%s', Base class '%s'",
  210.     cname,getcstring(id,sizeof(id),clgetname(sp)));
  211.     }
  212.     else {
  213.     push_nil();
  214.     stoken(tkn);
  215.     info("Class '%s'",cname);
  216.     }
  217.     frequire('{');
  218.  
  219.     /* create the new class object */
  220.     set_class(sp,newclass(cname,sp));
  221.     addentry(&classes,cname,ST_CLASS)->de_value = *sp;
  222.  
  223.     /* handle each variable declaration */
  224.     while ((tkn = token()) != '}') {
  225.  
  226.     /* check for static members */
  227.     if ((type = tkn) == T_STATIC)
  228.         tkn = token();
  229.  
  230.     /* get the first identifier */
  231.     if (tkn != T_IDENTIFIER)
  232.         parse_error("Expecting a member declaration");
  233.     strcpy(id,t_token);
  234.  
  235.     /* check for a member function declaration */
  236.     if ((tkn = token()) == '(') {
  237.         get_id_list(&fargs,")");
  238.         frequire(')');
  239.         addentry(clgetfunctions(sp),id,
  240.              type == T_STATIC ? ST_SFUNCTION : ST_FUNCTION);
  241.         freelist(&fargs);
  242.     }
  243.  
  244.     /* handle data members */
  245.     else {
  246.         table = (type == T_STATIC ? &smvars : &mvars);
  247.         addargument(table,id);
  248.         if (tkn == ',')
  249.         get_id_list(table,";");
  250.         else
  251.         stoken(tkn);
  252.     }        
  253.     frequire(';');
  254.     }
  255.  
  256.     /* store the member variable names */
  257.     i = (isnil(clgetbase(sp)) ? 0 : clgetsize(clgetbase(sp)));
  258.     for (p = mvars; p != NULL; p = p->arg_next) {
  259.     entry = addentry(clgetmembers(sp),p->arg_name,ST_DATA);
  260.     set_integer(&entry->de_value,i++);
  261.     }
  262.     sp->v.v_class->cl_size = i;
  263.     freelist(&mvars);
  264.  
  265.     /* store the static member variable names */
  266.     for (p = smvars; p != NULL; p = p->arg_next)
  267.     addentry(clgetmembers(sp),p->arg_name,ST_SDATA);
  268.     freelist(&smvars);
  269.     ++sp;
  270. }
  271.  
  272. /* findmember - find a class member */
  273. static DICT_ENTRY *findmember(class,name)
  274.   CLASS *class; char *name;
  275. {
  276.     DICT_ENTRY *entry;
  277.     if ((entry = findentry(&class->cl_members,name)) != NULL)
  278.     return (entry);
  279.     return (findentry(&class->cl_functions,name));
  280. }
  281.  
  282. /* rfindmember - recursive findmember */
  283. static DICT_ENTRY *rfindmember(class,name)
  284.   CLASS *class; char *name;
  285. {
  286.     DICT_ENTRY *entry;
  287.     if ((entry = findmember(class,name)) != NULL)
  288.     return (entry);
  289.     else if (!isnil(&class->cl_base))
  290.     return (rfindmember(claddr(&class->cl_base),name));
  291.     return (NULL);
  292. }
  293.  
  294. /* do_function - handle function declarations */
  295. static void do_function(name)
  296.   char *name;
  297. {
  298.     switch (token()) {
  299.     case '(':
  300.     do_regular_function(name);
  301.     break;
  302.     case T_CC:
  303.     check(1);
  304.     push_class(get_class(name));
  305.     do_member_function(sp);
  306.     ++sp;
  307.     break;
  308.     default:
  309.     parse_error("Expecting a function declaration");
  310.     break;
  311.     }
  312. }
  313.  
  314. /* do_regular_function - parse a regular function definition */
  315. static void do_regular_function(name)
  316.   char *name;
  317. {
  318.     /* enter the function name */
  319.     info("Function '%s'",name);
  320.     check(1);
  321.     push_var(addentry(&symbols,name,ST_SFUNCTION));
  322.  
  323.     /* compile the body of the function */
  324.     set_bytecode(&sp->v.v_var->de_value,do_code(name,&nil));
  325.     ++sp;
  326.  
  327.     /* free the argument and temporary symbol lists */
  328.     freelist(&arguments); freelist(&temporaries);
  329. }
  330.  
  331. /* do_member_function - parse a member function definition */
  332. static void do_member_function(class)
  333.   VALUE *class;
  334. {
  335.     char name[TKNSIZE+1],selector[TKNSIZE+1];
  336.     DICT_ENTRY *entry;
  337.     int tkn;
  338.     
  339.     /* get the selector */
  340.     frequire(T_IDENTIFIER);
  341.     strcpy(selector,t_token);
  342.     frequire('(');
  343.     getcstring(name,sizeof(name),clgetname(class));
  344.     info("Member function '%s::%s'",name,selector);
  345.  
  346.     /* make sure the type matches the declaration */
  347.     if ((entry = findmember(claddr(class),selector)) != NULL
  348.     &&  entry->de_type != ST_FUNCTION
  349.     &&  entry->de_type != ST_SFUNCTION)
  350.     parse_error("Illegal redefinition");
  351.  
  352.     /* compile the code */
  353.     check(1);
  354.     push_var(addentry(clgetfunctions(class),selector,ST_FUNCTION));
  355.     set_bytecode(&sp->v.v_var->de_value,do_code(selector,class));
  356.     ++sp;
  357.  
  358.     /* free the argument and temporary symbol lists */
  359.     freelist(&arguments); freelist(&temporaries);
  360. }
  361.  
  362. /* do_code - compile the code part of a function or method */
  363. static VECTOR *do_code(name,class)
  364.   char *name; VALUE *class;
  365. {
  366.     unsigned char *src,*dst;
  367.     int tcnt=0,nlits,tkn,i;
  368.     LITERAL *lit;
  369.  
  370.     /* initialize */
  371.     arguments = temporaries = NULL;
  372.     cptr = 0;
  373.  
  374.     /* add the implicit 'this' argument for member functions */
  375.     if (!isnil(class))
  376.     addargument(&arguments,"this");
  377.     methodclass = *class;
  378.     
  379.     /* get the argument list */
  380.     get_id_list(&arguments,";)");
  381.  
  382.     /* get temporary variables */
  383.     if ((tkn = token()) == ';') {
  384.     tcnt = get_id_list(&temporaries,")");
  385.     tkn = token();
  386.     }
  387.     require(tkn,')');
  388.     
  389.     /* reserve space for the temporaries */
  390.     if (tcnt > 0) {
  391.     putcbyte(OP_TSPACE);
  392.     putcbyte(tcnt);
  393.     }
  394.  
  395.     /* store the bytecodes, class and function name as the first literals */
  396.     addliteral(&literals,&lit);    /* will become the bytecode string */
  397.     addliteral(&literals,&lit);    /* class */
  398.     lit->lit_value = *class;
  399.     make_lit_string(name);    /* function name */
  400.  
  401.     /* compile the code */
  402.     putcbyte(OP_PUSH);
  403.     frequire('{');
  404.     do_block();
  405.     putcbyte(OP_RETURN);
  406.  
  407.     /* count the number of literals */
  408.     for (nlits = 0, lit = literals; lit != NULL; lit = lit->lit_next)
  409.     ++nlits;
  410.  
  411.     /* build the function */
  412.     check(1);
  413.     push_bytecode(newvector(nlits));
  414.     
  415.     /* create the code string */
  416.     set_string(&literals->lit_value,newstring(cptr));
  417.     src = cbuff;
  418.     dst = strgetdata(&literals->lit_value);
  419.     while (--cptr >= 0)
  420.     *dst++ = *src++;
  421.     
  422.     /* copy the literals */
  423.     for (i = 0, lit = literals; i < nlits; ++i, lit = lit->lit_next)
  424.     vecsetelement(sp,i,lit->lit_value);
  425.     freeliterals(&literals);
  426.  
  427.     /* show the generated code */
  428.     if (decode)
  429.     decode_procedure(sp);
  430.  
  431.     /* return the code object */
  432.     return (vecaddr(sp++));
  433. }
  434.  
  435. /* get_class - get the class associated with a symbol */
  436. static CLASS *get_class(name)
  437.   char *name;
  438. {
  439.     DICT_ENTRY *sym;
  440.     sym = findentry(&classes,name);
  441.     if (sym == NULL || sym->de_value.v_type != DT_CLASS)
  442.     parse_error("Expecting a class name");
  443.     return (claddr(&sym->de_value));
  444. }
  445.  
  446. /* do_statement - compile a single statement */
  447. static void do_statement()
  448. {
  449.     int tkn;
  450.     switch (tkn = token()) {
  451.     case T_IF:        do_if();    break;
  452.     case T_WHILE:    do_while();    break;
  453.     case T_DO:        do_dowhile();    break;
  454.     case T_FOR:        do_for();    break;
  455.     case T_BREAK:    do_break();    break;
  456.     case T_CONTINUE:    do_continue();    break;
  457.     case T_RETURN:    do_return();    break;
  458.     case '{':        do_block();    break;
  459.     case ';':        ;        break;
  460.     default:        stoken(tkn);
  461.             do_expr();
  462.             frequire(';');  break;
  463.     }
  464. }
  465.  
  466. /* do_if - compile the IF/ELSE expression */
  467. static void do_if()
  468. {
  469.     int tkn,nxt,end;
  470.  
  471.     /* compile the test expression */
  472.     do_test();
  473.  
  474.     /* skip around the 'then' clause if the expression is false */
  475.     putcbyte(OP_BRF);
  476.     nxt = putcword(0);
  477.  
  478.     /* compile the 'then' clause */
  479.     do_statement();
  480.  
  481.     /* compile the 'else' clause */
  482.     if ((tkn = token()) == T_ELSE) {
  483.     putcbyte(OP_BR);
  484.     end = putcword(0);
  485.     fixup(nxt,cptr);
  486.     do_statement();
  487.     nxt = end;
  488.     }
  489.     else
  490.     stoken(tkn);
  491.  
  492.     /* handle the end of the statement */
  493.     fixup(nxt,cptr);
  494. }
  495.  
  496. /* addbreak - add a break level to the stack */
  497. static int *addbreak(lbl)
  498.   int lbl;
  499. {
  500.     int *old=bsp;
  501.     if (++bsp < &bstack[SSIZE])
  502.     *bsp = lbl;
  503.     else
  504.     parse_error("Too many nested loops");
  505.     return (old);
  506. }
  507.  
  508. /* rembreak - remove a break level from the stack */
  509. static int rembreak(old,lbl)
  510.   int *old,lbl;
  511. {
  512.    return (bsp > old ? *bsp-- : lbl);
  513. }
  514.  
  515. /* addcontinue - add a continue level to the stack */
  516. static int *addcontinue(lbl)
  517.   int lbl;
  518. {
  519.     int *old=csp;
  520.     if (++csp < &cstack[SSIZE])
  521.     *csp = lbl;
  522.     else
  523.     parse_error("Too many nested loops");
  524.     return (old);
  525. }
  526.  
  527. /* remcontinue - remove a continue level from the stack */
  528. static remcontinue(old)
  529.   int *old;
  530. {
  531.     csp = old;
  532. }
  533.  
  534. /* do_while - compile the WHILE expression */
  535. static void do_while()
  536. {
  537.     int nxt,end,*ob,*oc;
  538.  
  539.     /* compile the test expression */
  540.     nxt = cptr;
  541.     do_test();
  542.  
  543.     /* skip around the loop body if the expression is false */
  544.     putcbyte(OP_BRF);
  545.     end = putcword(0);
  546.  
  547.     /* compile the loop body */
  548.     ob = addbreak(end);
  549.     oc = addcontinue(nxt);
  550.     do_statement();
  551.     end = rembreak(ob,end);
  552.     remcontinue(oc);
  553.  
  554.     /* branch back to the start of the loop */
  555.     putcbyte(OP_BR);
  556.     putcword(nxt);
  557.  
  558.     /* handle the end of the statement */
  559.     fixup(end,cptr);
  560. }
  561.  
  562. /* do_dowhile - compile the DO/WHILE expression */
  563. static void do_dowhile()
  564. {
  565.     int nxt,end=0,*ob,*oc;
  566.  
  567.     /* remember the start of the loop */
  568.     nxt = cptr;
  569.  
  570.     /* compile the loop body */
  571.     ob = addbreak(0);
  572.     oc = addcontinue(nxt);
  573.     do_statement();
  574.     end = rembreak(ob,end);
  575.     remcontinue(oc);
  576.  
  577.     /* compile the test expression */
  578.     frequire(T_WHILE);
  579.     do_test();
  580.     frequire(';');
  581.  
  582.     /* branch to the top if the expression is true */
  583.     putcbyte(OP_BRT);
  584.     putcword(nxt);
  585.  
  586.     /* handle the end of the statement */
  587.     fixup(end,cptr);
  588. }
  589.  
  590. /* do_for - compile the FOR statement */
  591. static void do_for()
  592. {
  593.     int tkn,nxt,end,body,update,*ob,*oc;
  594.  
  595.     /* compile the initialization expression */
  596.     frequire('(');
  597.     if ((tkn = token()) != ';') {
  598.     stoken(tkn);
  599.     do_expr();
  600.     frequire(';');
  601.     }
  602.  
  603.     /* compile the test expression */
  604.     nxt = cptr;
  605.     if ((tkn = token()) != ';') {
  606.     stoken(tkn);
  607.     do_expr();
  608.     frequire(';');
  609.     }
  610.  
  611.     /* branch to the loop body if the expression is true */
  612.     putcbyte(OP_BRT);
  613.     body = putcword(0);
  614.  
  615.     /* branch to the end if the expression is false */
  616.     putcbyte(OP_BR);
  617.     end = putcword(0);
  618.  
  619.     /* compile the update expression */
  620.     update = cptr;
  621.     if ((tkn = token()) != ')') {
  622.     stoken(tkn);
  623.     do_expr();
  624.     frequire(')');
  625.     }
  626.  
  627.     /* branch back to the test code */
  628.     putcbyte(OP_BR);
  629.     putcword(nxt);
  630.  
  631.     /* compile the loop body */
  632.     fixup(body,cptr);
  633.     ob = addbreak(end);
  634.     oc = addcontinue(update);
  635.     do_statement();
  636.     end = rembreak(ob,end);
  637.     remcontinue(oc);
  638.  
  639.     /* branch back to the update code */
  640.     putcbyte(OP_BR);
  641.     putcword(update);
  642.  
  643.     /* handle the end of the statement */
  644.     fixup(end,cptr);
  645. }
  646.  
  647. /* do_break - compile the BREAK statement */
  648. static void do_break()
  649. {
  650.     if (bsp >= bstack) {
  651.     putcbyte(OP_BR);
  652.     *bsp = putcword(*bsp);
  653.     }
  654.     else
  655.     parse_error("Break outside of loop");
  656. }
  657.  
  658. /* do_continue - compile the CONTINUE statement */
  659. static void do_continue()
  660. {
  661.     if (csp >= cstack) {
  662.     putcbyte(OP_BR);
  663.     putcword(*csp);
  664.     }
  665.     else
  666.     parse_error("Continue outside of loop");
  667. }
  668.  
  669. /* do_block - compile the {} expression */
  670. static void do_block()
  671. {
  672.     int tkn;
  673.     if ((tkn = token()) != '}') {
  674.     do {
  675.         stoken(tkn);
  676.         do_statement();
  677.     } while ((tkn = token()) != '}');
  678.     }
  679.     else
  680.     putcbyte(OP_NIL);
  681. }
  682.  
  683. /* do_return - handle the RETURN expression */
  684. static void do_return()
  685. {
  686.     do_expr();
  687.     frequire(';');
  688.     putcbyte(OP_RETURN);
  689. }
  690.  
  691. /* do_test - compile a test expression */
  692. static void do_test()
  693. {
  694.     frequire('(');
  695.     do_expr();
  696.     frequire(')');
  697. }
  698.  
  699. /* do_expr - parse an expression */
  700. static void do_expr()
  701. {
  702.     PVAL pv;
  703.     do_expr1(&pv);
  704.     rvalue(&pv);
  705. }
  706.  
  707. /* rvalue - get the rvalue of a partial expression */
  708. static rvalue(pv)
  709.   PVAL *pv;
  710. {
  711.     if (pv->fcn) {
  712.     (*pv->fcn)(LOAD,pv->val);
  713.     pv->fcn = NULL;
  714.     }
  715. }
  716.  
  717. /* chklvalue - make sure we've got an lvalue */
  718. static chklvalue(pv)
  719.   PVAL *pv;
  720. {
  721.     if (pv->fcn == NULL)
  722.     parse_error("Expecting an lvalue");
  723. }
  724.  
  725. /* do_expr1 - handle the ',' operator */
  726. static void do_expr1(pv)
  727.   PVAL *pv;
  728. {
  729.     int tkn;
  730.     do_expr2(pv);
  731.     while ((tkn = token()) == ',') {
  732.     rvalue(pv);
  733.     do_expr1(pv); rvalue(pv);
  734.     }
  735.     stoken(tkn);
  736. }
  737.  
  738. /* do_expr2 - handle the assignment operators */
  739. static void do_expr2(pv)
  740.   PVAL *pv;
  741. {
  742.     int tkn,nxt,end;
  743.     PVAL rhs;
  744.     do_expr3(pv);
  745.     while ((tkn = token()) == '='
  746.     ||     tkn == T_ADDEQ || tkn == T_SUBEQ
  747.     ||     tkn == T_MULEQ || tkn == T_DIVEQ || tkn == T_REMEQ
  748.     ||     tkn == T_ANDEQ || tkn == T_OREQ  || tkn == T_XOREQ
  749.     ||     tkn == T_SHLEQ || tkn == T_SHLEQ) {
  750.     chklvalue(pv);
  751.     switch (tkn) {
  752.     case '=':
  753.         (*pv->fcn)(PUSH,0);
  754.         do_expr1(&rhs); rvalue(&rhs);
  755.         (*pv->fcn)(STORE,pv->val);
  756.         break;
  757.     case T_ADDEQ:        do_assignment(pv,OP_ADD);        break;
  758.     case T_SUBEQ:        do_assignment(pv,OP_SUB);        break;
  759.     case T_MULEQ:        do_assignment(pv,OP_MUL);        break;
  760.     case T_DIVEQ:        do_assignment(pv,OP_DIV);        break;
  761.     case T_REMEQ:        do_assignment(pv,OP_REM);        break;
  762.     case T_ANDEQ:        do_assignment(pv,OP_BAND);        break;
  763.     case T_OREQ:        do_assignment(pv,OP_BOR);        break;
  764.     case T_XOREQ:        do_assignment(pv,OP_XOR);        break;
  765.     case T_SHLEQ:        do_assignment(pv,OP_SHL);        break;
  766.     case T_SHREQ:        do_assignment(pv,OP_SHR);        break;
  767.      }
  768.     pv->fcn = NULL;
  769.     }
  770.     stoken(tkn);
  771. }
  772.  
  773. /* do_assignment - handle assignment operations */
  774. static void do_assignment(pv,op)
  775.   PVAL *pv; int op;
  776. {
  777.     PVAL rhs;
  778.     (*pv->fcn)(DUP,0);
  779.     (*pv->fcn)(LOAD,pv->val);
  780.     putcbyte(OP_PUSH);
  781.     do_expr1(&rhs); rvalue(&rhs);
  782.     putcbyte(op);
  783.     (*pv->fcn)(STORE,pv->val);
  784. }
  785.  
  786. /* do_expr3 - handle the '?:' operator */
  787. static void do_expr3(pv)
  788.   PVAL *pv;
  789. {
  790.     int tkn,nxt,end;
  791.     do_expr4(pv);
  792.     while ((tkn = token()) == '?') {
  793.     rvalue(pv);
  794.     putcbyte(OP_BRF);
  795.     nxt = putcword(0);
  796.     do_expr1(pv); rvalue(pv);
  797.     frequire(':');
  798.     putcbyte(OP_BR);
  799.     end = putcword(0);
  800.     fixup(nxt,cptr);
  801.     do_expr1(pv); rvalue(pv);
  802.     fixup(end,cptr);
  803.     }
  804.     stoken(tkn);
  805. }
  806.  
  807. /* do_expr4 - handle the '||' operator */
  808. static void do_expr4(pv)
  809.   PVAL *pv;
  810. {
  811.     int tkn,end=0;
  812.     do_expr5(pv);
  813.     while ((tkn = token()) == T_OR) {
  814.     rvalue(pv);
  815.     putcbyte(OP_BRT);
  816.     end = putcword(end);
  817.     do_expr5(pv); rvalue(pv);
  818.     }
  819.     fixup(end,cptr);
  820.     stoken(tkn);
  821. }
  822.  
  823. /* do_expr5 - handle the '&&' operator */
  824. static void do_expr5(pv)
  825.   PVAL *pv;
  826. {
  827.     int tkn,end=0;
  828.     do_expr6(pv);
  829.     while ((tkn = token()) == T_AND) {
  830.     rvalue(pv);
  831.     putcbyte(OP_BRF);
  832.     end = putcword(end);
  833.     do_expr6(pv); rvalue(pv);
  834.     }
  835.     fixup(end,cptr);
  836.     stoken(tkn);
  837. }
  838.  
  839. /* do_expr6 - handle the '|' operator */
  840. static void do_expr6(pv)
  841.   PVAL *pv;
  842. {
  843.     int tkn;
  844.     do_expr7(pv);
  845.     while ((tkn = token()) == '|') {
  846.     rvalue(pv);
  847.     putcbyte(OP_PUSH);
  848.     do_expr7(pv); rvalue(pv);
  849.     putcbyte(OP_BOR);
  850.     }
  851.     stoken(tkn);
  852. }
  853.  
  854. /* do_expr7 - handle the '^' operator */
  855. static void do_expr7(pv)
  856.   PVAL *pv;
  857. {
  858.     int tkn;
  859.     do_expr8(pv);
  860.     while ((tkn = token()) == '^') {
  861.     rvalue(pv);
  862.     putcbyte(OP_PUSH);
  863.     do_expr8(pv); rvalue(pv);
  864.     putcbyte(OP_XOR);
  865.     }
  866.     stoken(tkn);
  867. }
  868.  
  869. /* do_expr8 - handle the '&' operator */
  870. static void do_expr8(pv)
  871.   PVAL *pv;
  872. {
  873.     int tkn;
  874.     do_expr9(pv);
  875.     while ((tkn = token()) == '&') {
  876.     rvalue(pv);
  877.     putcbyte(OP_PUSH);
  878.     do_expr9(pv); rvalue(pv);
  879.     putcbyte(OP_BAND);
  880.     }
  881.     stoken(tkn);
  882. }
  883.  
  884. /* do_expr9 - handle the '==' and '!=' operators */
  885. static void do_expr9(pv)
  886.   PVAL *pv;
  887. {
  888.     int tkn,op;
  889.     do_expr10(pv);
  890.     while ((tkn = token()) == T_EQ || tkn == T_NE) {
  891.     switch (tkn) {
  892.     case T_EQ: op = OP_EQ; break;
  893.     case T_NE: op = OP_NE; break;
  894.     }
  895.     rvalue(pv);
  896.     putcbyte(OP_PUSH);
  897.     do_expr10(pv); rvalue(pv);
  898.     putcbyte(op);
  899.     }
  900.     stoken(tkn);
  901. }
  902.  
  903. /* do_expr10 - handle the '<', '<=', '>=' and '>' operators */
  904. static void do_expr10(pv)
  905.   PVAL *pv;
  906. {
  907.     int tkn,op;
  908.     do_expr11(pv);
  909.     while ((tkn = token()) == '<' || tkn == T_LE || tkn == T_GE || tkn == '>') {
  910.     switch (tkn) {
  911.     case '<':  op = OP_LT; break;
  912.     case T_LE: op = OP_LE; break;
  913.     case T_GE: op = OP_GE; break;
  914.     case '>':  op = OP_GT; break;
  915.     }
  916.     rvalue(pv);
  917.     putcbyte(OP_PUSH);
  918.     do_expr11(pv); rvalue(pv);
  919.     putcbyte(op);
  920.     }
  921.     stoken(tkn);
  922. }
  923.  
  924. /* do_expr11 - handle the '<<' and '>>' operators */
  925. static void do_expr11(pv)
  926.   PVAL *pv;
  927. {
  928.     int tkn,op;
  929.     do_expr12(pv);
  930.     while ((tkn = token()) == T_SHL || tkn == T_SHR) {
  931.     switch (tkn) {
  932.     case T_SHL: op = OP_SHL; break;
  933.     case T_SHR: op = OP_SHR; break;
  934.     }
  935.     rvalue(pv);
  936.     putcbyte(OP_PUSH);
  937.     do_expr12(pv); rvalue(pv);
  938.     putcbyte(op);
  939.     }
  940.     stoken(tkn);
  941. }
  942.  
  943. /* do_expr12 - handle the '+' and '-' operators */
  944. static void do_expr12(pv)
  945.   PVAL *pv;
  946. {
  947.     int tkn,op;
  948.     do_expr13(pv);
  949.     while ((tkn = token()) == '+' || tkn == '-') {
  950.     switch (tkn) {
  951.     case '+': op = OP_ADD; break;
  952.     case '-': op = OP_SUB; break;
  953.     }
  954.     rvalue(pv);
  955.     putcbyte(OP_PUSH);
  956.     do_expr13(pv); rvalue(pv);
  957.     putcbyte(op);
  958.     }
  959.     stoken(tkn);
  960. }
  961.  
  962. /* do_expr13 - handle the '*' and '/' operators */
  963. static void do_expr13(pv)
  964.   PVAL *pv;
  965. {
  966.     int tkn,op;
  967.     do_expr14(pv);
  968.     while ((tkn = token()) == '*' || tkn == '/' || tkn == '%') {
  969.     switch (tkn) {
  970.     case '*': op = OP_MUL; break;
  971.     case '/': op = OP_DIV; break;
  972.     case '%': op = OP_REM; break;
  973.     }
  974.     rvalue(pv);
  975.     putcbyte(OP_PUSH);
  976.     do_expr14(pv); rvalue(pv);
  977.     putcbyte(op);
  978.     }
  979.     stoken(tkn);
  980. }
  981.  
  982. /* do_expr14 - handle unary operators */
  983. static void do_expr14(pv)
  984.   PVAL *pv;
  985. {
  986.     int tkn;
  987.     switch (tkn = token()) {
  988.     case '-':
  989.     do_expr15(pv); rvalue(pv);
  990.     putcbyte(OP_NEG);
  991.     break;
  992.     case '!':
  993.     do_expr15(pv); rvalue(pv);
  994.     putcbyte(OP_NOT);
  995.     break;
  996.     case '~':
  997.     do_expr15(pv); rvalue(pv);
  998.     putcbyte(OP_BNOT);
  999.     break;
  1000.     case T_INC:
  1001.     do_preincrement(pv,OP_INC);
  1002.     break;
  1003.     case T_DEC:
  1004.     do_preincrement(pv,OP_DEC);
  1005.     break;
  1006.     case T_NEW:
  1007.     do_new(pv);
  1008.     break;
  1009.     default:
  1010.     stoken(tkn);
  1011.     do_expr15(pv);
  1012.     return;
  1013.     }
  1014. }
  1015.  
  1016. /* do_preincrement - handle prefix '++' and '--' */
  1017. static void do_preincrement(pv,op)
  1018.   PVAL *pv; int op;
  1019. {
  1020.     do_expr15(pv);
  1021.     chklvalue(pv);
  1022.     (*pv->fcn)(DUP,0);
  1023.     (*pv->fcn)(LOAD,pv->val);
  1024.     putcbyte(op);
  1025.     (*pv->fcn)(STORE,pv->val);
  1026.     pv->fcn = NULL;
  1027. }
  1028.  
  1029. /* do_postincrement - handle postfix '++' and '--' */
  1030. static void do_postincrement(pv,op)
  1031.   PVAL *pv; int op;
  1032. {
  1033.     chklvalue(pv);
  1034.     (*pv->fcn)(DUP,0);
  1035.     (*pv->fcn)(LOAD,pv->val);
  1036.     putcbyte(op);
  1037.     (*pv->fcn)(STORE,pv->val);
  1038.     putcbyte(op == OP_INC ? OP_DEC : OP_INC);
  1039.     pv->fcn = NULL;
  1040. }
  1041.  
  1042. /* do_new - handle the 'new' operator */
  1043. static void do_new(pv)
  1044.   PVAL *pv;
  1045. {
  1046.     char selector[TKNSIZE+1];
  1047.     LITERAL *lit;
  1048.     CLASS *class;
  1049.  
  1050.     frequire(T_IDENTIFIER);
  1051.     strcpy(selector,t_token);
  1052.  
  1053.     class = get_class(selector);
  1054.  
  1055.     code_literal(addliteral(&literals,&lit));
  1056.     set_class(&lit->lit_value,class);
  1057.  
  1058.     putcbyte(OP_NEW);
  1059.     pv->fcn = NULL;
  1060.     
  1061.     do_send(selector,pv);
  1062. }
  1063.  
  1064. /* do_expr15 - handle function calls */
  1065. static void do_expr15(pv)
  1066.   PVAL *pv;
  1067. {
  1068.     char selector[TKNSIZE+1];
  1069.     int tkn;
  1070.     do_primary(pv);
  1071.     while ((tkn = token()) == '('
  1072.     ||     tkn == '['
  1073.     ||     tkn == T_MEMREF
  1074.     ||     tkn == T_INC
  1075.     ||     tkn == T_DEC)
  1076.     switch (tkn) {
  1077.     case '(':
  1078.         do_call(pv);
  1079.         break;
  1080.     case '[':
  1081.         do_index(pv);
  1082.         break;
  1083.     case T_MEMREF:
  1084.         frequire(T_IDENTIFIER);
  1085.         strcpy(selector,t_token);
  1086.         do_send(selector,pv);
  1087.         break;
  1088.     case T_INC:
  1089.         do_postincrement(pv,OP_INC);
  1090.         break;
  1091.     case T_DEC:
  1092.         do_postincrement(pv,OP_DEC);
  1093.         break;
  1094.     }
  1095.     stoken(tkn);
  1096. }
  1097.  
  1098. /* do_primary - parse a primary expression and unary operators */
  1099. static void do_primary(pv)
  1100.   PVAL *pv;
  1101. {
  1102.     char id[TKNSIZE+1];
  1103.     DICT_ENTRY *entry;
  1104.     CLASS *class;
  1105.     int tkn;
  1106.     switch (token()) {
  1107.     case '(':
  1108.     do_expr1(pv);
  1109.     frequire(')');
  1110.     break;
  1111.     case T_NUMBER:
  1112.     do_lit_integer((long)t_value);
  1113.     pv->fcn = NULL;
  1114.     break;
  1115.     case T_STRING:
  1116.     do_lit_string(t_token);
  1117.     pv->fcn = NULL;
  1118.     break;
  1119.     case T_NIL:
  1120.     putcbyte(OP_NIL);
  1121.     pv->fcn = NULL;
  1122.     break;
  1123.     case T_IDENTIFIER:
  1124.     strcpy(id,t_token);
  1125.     if ((tkn = token()) == T_CC) {
  1126.         class = get_class(id);
  1127.         frequire(T_IDENTIFIER);
  1128.         if (!findclassvariable(class,t_token,pv))
  1129.         parse_error("Not a class member");
  1130.     }
  1131.     else {
  1132.         stoken(tkn);
  1133.         findvariable(id,pv);
  1134.     }
  1135.     break;
  1136.     default:
  1137.     parse_error("Expecting a primary expression");
  1138.     break;
  1139.     }
  1140. }
  1141.  
  1142. /* do_call - compile a function call */
  1143. static void do_call(pv)
  1144.   PVAL *pv;
  1145. {
  1146.     int tkn,n=0;
  1147.     
  1148.     /* get the value of the function */
  1149.     rvalue(pv);
  1150.  
  1151.     /* compile each argument expression */
  1152.     if ((tkn = token()) != ')') {
  1153.     stoken(tkn);
  1154.     do {
  1155.         putcbyte(OP_PUSH);
  1156.         do_expr2(pv); rvalue(pv);
  1157.         ++n;
  1158.     } while ((tkn = token()) == ',');
  1159.     }
  1160.     require(tkn,')');
  1161.     putcbyte(OP_CALL);
  1162.     putcbyte(n);
  1163.  
  1164.     /* we've got an rvalue now */
  1165.     pv->fcn = NULL;
  1166. }
  1167.  
  1168. /* do_send - compile a message sending expression */
  1169. static void do_send(selector,pv)
  1170.   char *selector; PVAL *pv;
  1171. {
  1172.     LITERAL *lit;
  1173.     int tkn,n=1;
  1174.     
  1175.     /* get the receiver value */
  1176.     rvalue(pv);
  1177.  
  1178.     /* generate code to push the selector */
  1179.     putcbyte(OP_PUSH);
  1180.     code_literal(addliteral(&literals,&lit));
  1181.     set_string(&lit->lit_value,makestring(selector));
  1182.  
  1183.     /* compile the argument list */
  1184.     frequire('(');
  1185.     if ((tkn = token()) != ')') {
  1186.     stoken(tkn);
  1187.     do {
  1188.         putcbyte(OP_PUSH);
  1189.         do_expr2(pv); rvalue(pv);
  1190.         ++n;
  1191.     } while ((tkn = token()) == ',');
  1192.     }
  1193.     require(tkn,')');
  1194.  
  1195.     /* send the message */
  1196.     putcbyte(OP_SEND);
  1197.     putcbyte(n);
  1198.  
  1199.     /* we've got an rvalue now */
  1200.     pv->fcn = NULL;
  1201. }
  1202.  
  1203. /* do_index - compile an indexing operation */
  1204. static void do_index(pv)
  1205.   PVAL *pv;
  1206. {
  1207.     int code_index();
  1208.     rvalue(pv);
  1209.     putcbyte(OP_PUSH);
  1210.     do_expr();
  1211.     frequire(']');
  1212.     pv->fcn = code_index;
  1213. }
  1214.  
  1215. /* get_id_list - get a comma separated list of identifiers */
  1216. static int get_id_list(list,term)
  1217.   ARGUMENT **list; char *term;
  1218. {
  1219.     char *strchr();
  1220.     int tkn,cnt=0;
  1221.     tkn = token();
  1222.     if (!strchr(term,tkn)) {
  1223.     stoken(tkn);
  1224.     do {
  1225.         frequire(T_IDENTIFIER);
  1226.         addargument(list,t_token);
  1227.         ++cnt;
  1228.     } while ((tkn = token()) == ',');
  1229.     }
  1230.     stoken(tkn);
  1231.     return (cnt);
  1232. }
  1233.  
  1234. /* addargument - add a formal argument */
  1235. static addargument(list,name)
  1236.   ARGUMENT **list; char *name;
  1237. {
  1238.     ARGUMENT *arg;
  1239.     arg = (ARGUMENT *)getmemory(sizeof(ARGUMENT));
  1240.     arg->arg_name = copystring(name);
  1241.     arg->arg_next = *list;
  1242.     *list = arg;
  1243. }
  1244.  
  1245. /* freelist - free a list of arguments or temporaries */
  1246. static freelist(plist)
  1247.   ARGUMENT **plist;
  1248. {
  1249.     ARGUMENT *this,*next;
  1250.     for (this = *plist, *plist = NULL; this != NULL; this = next) {
  1251.     next = this->arg_next;
  1252.     free(this->arg_name);
  1253.     free((char *)this);
  1254.     }
  1255. }
  1256.  
  1257. /* findarg - find an argument offset */
  1258. static int findarg(name)
  1259.   char *name;
  1260. {
  1261.     ARGUMENT *arg;
  1262.     int n;
  1263.     for (n = 0, arg = arguments; arg; n++, arg = arg->arg_next)
  1264.     if (strcmp(name,arg->arg_name) == 0)
  1265.         return (n);
  1266.     return (-1);
  1267. }
  1268.  
  1269. /* findtmp - find a temporary variable offset */
  1270. static int findtmp(name)
  1271.   char *name;
  1272. {
  1273.     ARGUMENT *tmp;
  1274.     int n;
  1275.     for (n = 0, tmp = temporaries; tmp; n++, tmp = tmp->arg_next)
  1276.     if (strcmp(name,tmp->arg_name) == 0)
  1277.         return (n);
  1278.     return (-1);
  1279. }
  1280.  
  1281. /* finddatamember - find a class data member */
  1282. static DICT_ENTRY *finddatamember(name)
  1283.   char *name;
  1284. {
  1285.     DICT_ENTRY *entry;
  1286.     VALUE *class;
  1287.     if (!isnil(class)) {
  1288.     class = &methodclass;
  1289.     do {
  1290.         if ((entry = findentry(clgetmembers(class),name)) != NULL)
  1291.         return (entry);
  1292.         class = clgetbase(class);
  1293.     } while (!isnil(class));
  1294.     }
  1295.     return (NULL);
  1296. }
  1297.  
  1298. /* addliteral - add a literal */
  1299. static int addliteral(list,pval)
  1300.   LITERAL **list,**pval;
  1301. {
  1302.     LITERAL **plit,*lit;
  1303.     int n=0;
  1304.     for (plit = list; (lit = *plit) != NULL; plit = &lit->lit_next)
  1305.     ++n;
  1306.     lit = (LITERAL *)getmemory(sizeof(LITERAL));
  1307.     set_nil(&lit->lit_value);
  1308.     lit->lit_next = NULL;
  1309.     *pval = *plit = lit;
  1310.     return (n);
  1311. }
  1312.  
  1313. /* freeliterals - free a list of literals */
  1314. static freeliterals(plist)
  1315.   LITERAL **plist;
  1316. {
  1317.     LITERAL *this,*next;
  1318.     for (this = *plist, *plist = NULL; this != NULL; this = next) {
  1319.     next = this->lit_next;
  1320.     free((char *)this);
  1321.     }
  1322. }
  1323.  
  1324. /* frequire - fetch a token and check it */
  1325. static frequire(rtkn)
  1326.   int rtkn;
  1327. {
  1328.     require(token(),rtkn);
  1329. }
  1330.  
  1331. /* require - check for a required token */
  1332. static require(tkn,rtkn)
  1333.   int tkn,rtkn;
  1334. {
  1335.     char msg[100],tknbuf[100],*tkn_name();
  1336.     if (tkn != rtkn) {
  1337.     strcpy(tknbuf,tkn_name(rtkn));
  1338.     sprintf(msg,"Expecting '%s', found '%s'",tknbuf,tkn_name(tkn));
  1339.     parse_error(msg);
  1340.     }
  1341. }
  1342.  
  1343. /* do_lit_integer - compile a literal integer */
  1344. static void do_lit_integer(n)
  1345.   long n;
  1346. {
  1347.     LITERAL *lit;
  1348.     code_literal(addliteral(&literals,&lit));
  1349.     set_integer(&lit->lit_value,n);
  1350. }
  1351.  
  1352. /* do_lit_string - compile a literal string */
  1353. static void do_lit_string(str)
  1354.   char *str;
  1355. {
  1356.     code_literal(make_lit_string(str));
  1357. }
  1358.  
  1359. /* make_lit_string - make a literal string */
  1360. static int make_lit_string(str)
  1361.   char *str;
  1362. {
  1363.     LITERAL *lit;
  1364.     int n;
  1365.     n = addliteral(&literals,&lit);
  1366.     set_string(&lit->lit_value,makestring(str));
  1367.     return (n);
  1368. }
  1369.  
  1370. /* make_lit_variable - make a literal reference to a variable */
  1371. static int make_lit_variable(sym)
  1372.   DICT_ENTRY *sym;
  1373. {
  1374.     LITERAL *lit;
  1375.     int n;
  1376.     n = addliteral(&literals,&lit);
  1377.     set_var(&lit->lit_value,sym);
  1378.     return (n);
  1379. }
  1380.  
  1381. /* findvariable - find a variable */
  1382. static findvariable(id,pv)
  1383.   char *id; PVAL *pv;
  1384. {    
  1385.     int code_argument(),code_temporary(),code_variable();
  1386.     DICT_ENTRY *entry;
  1387.     int n;
  1388.     if ((n = findarg(id)) >= 0) {
  1389.     pv->fcn = code_argument;
  1390.     pv->val = n;
  1391.     }
  1392.     else if ((n = findtmp(id)) >= 0) {
  1393.     pv->fcn = code_temporary;
  1394.     pv->val = n;
  1395.     }
  1396.     else if (isnil(&methodclass)
  1397.           || !findclassvariable(claddr(&methodclass),id,pv)) {
  1398.     pv->fcn = code_variable;
  1399.     pv->val = make_lit_variable(addentry(&symbols,id,ST_SDATA));
  1400.     }
  1401. }
  1402.  
  1403. /* findclassvariable - find a class member variable */
  1404. static int findclassvariable(class,name,pv)
  1405.   CLASS *class; char *name; PVAL *pv;
  1406. {
  1407.     int code_member(),code_variable();
  1408.     DICT_ENTRY *entry;
  1409.     if ((entry = rfindmember(class,name)) == NULL)
  1410.     return (FALSE);
  1411.     switch (entry->de_type) {
  1412.     case ST_DATA:
  1413.     pv->fcn = code_member;
  1414.     pv->val = entry->de_value.v.v_integer;
  1415.     break;
  1416.     case ST_SDATA:
  1417.     pv->fcn = code_variable;
  1418.            pv->val = make_lit_variable(entry);
  1419.     break;
  1420.     case ST_FUNCTION:
  1421.     findvariable("this",pv);
  1422.     do_send(name,pv);
  1423.     break;
  1424.     case ST_SFUNCTION:
  1425.     code_variable(LOAD,make_lit_variable(entry));
  1426.     pv->fcn = NULL;
  1427.     break;
  1428.     }
  1429.     return (TRUE);
  1430. }
  1431.  
  1432. /* code_argument - compile an argument reference */
  1433. static code_argument(fcn,n)
  1434.   int fcn,n;
  1435. {
  1436.     switch (fcn) {
  1437.     case LOAD:    putcbyte(OP_AREF); putcbyte(n); break;
  1438.     case STORE:    putcbyte(OP_ASET); putcbyte(n); break;
  1439.     }
  1440. }
  1441.  
  1442. /* code_temporary - compile a temporary variable reference */
  1443. static code_temporary(fcn,n)
  1444.   int fcn,n;
  1445. {
  1446.     switch (fcn) {
  1447.     case LOAD:    putcbyte(OP_TREF); putcbyte(n); break;
  1448.     case STORE:    putcbyte(OP_TSET); putcbyte(n); break;
  1449.     }
  1450. }
  1451.  
  1452. /* code_member - compile a data member reference */
  1453. static code_member(fcn,n)
  1454.   int fcn,n;
  1455. {
  1456.     switch (fcn) {
  1457.     case LOAD:    putcbyte(OP_MREF); putcbyte(n); break;
  1458.     case STORE:    putcbyte(OP_MSET); putcbyte(n); break;
  1459.     }
  1460. }
  1461.  
  1462. /* code_variable - compile a variable reference */
  1463. static code_variable(fcn,n)
  1464.   int fcn,n;
  1465. {
  1466.     switch (fcn) {
  1467.     case LOAD:    putcbyte(OP_REF); putcbyte(n); break;
  1468.     case STORE:    putcbyte(OP_SET); putcbyte(n); break;
  1469.     }
  1470. }
  1471.  
  1472. /* code_index - compile an indexed reference */
  1473. static code_index(fcn,n)
  1474.   int fcn,n;
  1475. {
  1476.     switch (fcn) {
  1477.     case LOAD:    putcbyte(OP_VREF); break;
  1478.     case STORE:    putcbyte(OP_VSET); break;
  1479.     case PUSH:  putcbyte(OP_PUSH); break;
  1480.     case DUP:    putcbyte(OP_DUP2); break;
  1481.     }
  1482. }
  1483.  
  1484. /* code_literal - compile a literal reference */
  1485. static code_literal(n)
  1486.   int n;
  1487. {
  1488.     putcbyte(OP_LIT);
  1489.     putcbyte(n);
  1490. }
  1491.  
  1492. /* putcbyte - put a code byte into data space */
  1493. static int putcbyte(b)
  1494.   int b;
  1495. {
  1496.     if (cptr >= CMAX)
  1497.     parse_error("Insufficient code space");
  1498.     cbuff[cptr] = b;
  1499.     return (cptr++);
  1500. }
  1501.  
  1502. /* putcword - put a code word into data space */
  1503. static int putcword(w)
  1504.   int w;
  1505. {
  1506.     putcbyte(w);
  1507.     putcbyte(w >> 8);
  1508.     return (cptr-2);
  1509. }
  1510.  
  1511. /* fixup - fixup a reference chain */
  1512. static fixup(chn,val)
  1513.   int chn,val;
  1514. {
  1515.     int hval,nxt;
  1516.     for (hval = val >> 8; chn != 0; chn = nxt) {
  1517.     nxt = (cbuff[chn] & 0xFF) | (cbuff[chn+1] << 8);
  1518.     cbuff[chn] = val;
  1519.     cbuff[chn+1] = hval;
  1520.     }
  1521. }
  1522.  
  1523. /* copystring - make a copy of a string */
  1524. static char *copystring(str)
  1525.   char *str;
  1526. {
  1527.     char *val;
  1528.     val = getmemory(strlen(str)+1);
  1529.     strcpy(val,str);
  1530.     return (val);
  1531. }
  1532.  
  1533. /* getmemory - allocate memory and complain if there isn't enough */
  1534. static char *getmemory(size)
  1535.   int size;
  1536. {
  1537. /*  char *calloc(); */
  1538.     char *val;
  1539.     if ((val = calloc(1,size)) == NULL)
  1540.     error("Insufficient memory");
  1541.     return (val);
  1542. }
  1543.