home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / rtt / rttilc.c < prev    next >
C/C++ Source or Header  |  1996-03-22  |  42KB  |  1,404 lines

  1. /*
  2.  * rttilc.c - routines to construct pieces of C code to put in the data base
  3.  *  as in-line code.
  4.  *
  5.  * In-line C code is represented internally as a linked list of structures.
  6.  * The information contained in each structure depends on the type of code
  7.  * being represented. Some structures contain other fragments of C code.
  8.  * Code that does not require special processing is stored as strings. These
  9.  * strings are accumulated in a buffer until it is full or code that cannot
  10.  * be represented as a string must be produced. At that point, the string
  11.  * in placed in a structure and put on the list.
  12.  */
  13. #include "rtt.h"
  14.  
  15. #ifndef Rttx
  16.  
  17. /*
  18.  * prototypes for static functions.
  19.  */
  20. hidden novalue add_ptr   Params((struct node *dcltor));
  21. hidden novalue alloc_ilc Params((int il_c_type));
  22. hidden novalue flush_str Params((noargs));
  23. hidden novalue ilc_chnl  Params((struct token *t));
  24. hidden novalue ilc_cnv   Params((struct node *cnv_typ, struct node *src,
  25.                            struct node *dflt, struct node *dest));
  26. hidden novalue ilc_cgoto Params((int neg, struct node *cond, word lbl));
  27. hidden novalue ilc_goto  Params((word lbl));
  28. hidden novalue ilc_lbl   Params((word lbl));
  29. hidden novalue ilc_ret   Params((struct token *t, int ilc_typ, struct node *n));
  30. hidden novalue ilc_str   Params((char *s));
  31. hidden novalue ilc_tok   Params((struct token *t));
  32. hidden novalue ilc_var   Params((struct sym_entry *sym, int just_desc,
  33.                            int may_mod));
  34. hidden novalue ilc_walk  Params((struct node *n, int may_mod, int const_cast));
  35. hidden novalue init_ilc  Params((noargs));
  36. hidden novalue insrt_str Params((noargs));
  37. hidden novalue new_ilc   Params((int il_c_type));
  38. hidden    struct    il_c    *sep_ilc    Params((char *s1,struct node *n,char *s2));
  39.  
  40. #define SBufSz 256
  41.  
  42. static char sbuf[SBufSz];      /* buffer for constructing fragments of code */
  43. static int nxt_char;           /* next position in sbuf */
  44. static struct token *line_ref; /* "recent" token for comparing line number */
  45. static struct il_c ilc_base;   /* base for list of in-line C code */
  46. static struct il_c *ilc_cur;   /* current end of list of in-line C code */
  47. static int insert_nl;          /* flag: new-line should be inserted in code */
  48. static word cont_lbl = 0;      /* destination label for C continue statement */
  49. static word brk_lbl = 0;       /* destination label for C break statement */
  50.  
  51. /*
  52.  * inlin_c - Create a self-contained piece of in-line C code from a syntax
  53.  *   sub-tree.
  54.  */
  55. struct il_c *inlin_c(n, may_mod)
  56. struct node *n;
  57. int may_mod;
  58.    {
  59.    init_ilc();              /* initialize code list and string buffer */
  60.    ilc_walk(n, may_mod, 0); /* translate the syntax sub-tree */
  61.    flush_str();            /* flush string buffer to code list */
  62.    return ilc_base.next;
  63.    }
  64.  
  65. /*
  66.  * simpl_dcl - produce a simple declaration both in the output file and as
  67.  *   in-line C code.
  68.  */
  69. struct il_c *simpl_dcl(tqual, addr_of, sym)
  70. char *tqual;
  71. int addr_of;
  72. struct sym_entry *sym;
  73.    {
  74.    init_ilc();             /* initialize code list and string buffer */
  75.    prt_str(tqual, 0);
  76.    ilc_str(tqual);
  77.    if (addr_of) {
  78.       prt_str("*", 0);
  79.       ilc_str("*");
  80.       }
  81.    prt_str(sym->image, 0);
  82.    ilc_str(sym->image);
  83.    prt_str(";", 0);
  84.    ForceNl();
  85.    flush_str();            /* flush string buffer to code list */
  86.    return ilc_base.next;
  87.    }
  88.  
  89. /*
  90.  * parm_dcl - produce the declaration for a parameter to a body function.
  91.  *   Print it in the output file and proceduce in-line C code for it.
  92.  */
  93. struct il_c *parm_dcl(addr_of, sym)
  94. int addr_of;
  95. struct sym_entry *sym;
  96.    {
  97.    init_ilc();        /* initialize code list and string buffer */
  98.  
  99.    /*
  100.     * Produce type-qualifier list, but without non-type information.
  101.     */
  102.    just_type(sym->u.declare_var.tqual, 0, 1);
  103.    prt_str(" ", 0);
  104.    ilc_str(" ");
  105.  
  106.    /*
  107.     * If the caller requested another level of indirection on the
  108.     *  declaration add it.
  109.     */
  110.    if (addr_of)
  111.       add_ptr(sym->u.declare_var.dcltor);
  112.    else {
  113.       c_walk(sym->u.declare_var.dcltor, 0, 0);
  114.       ilc_walk(sym->u.declare_var.dcltor, 0, 0);
  115.       }
  116.    prt_str(";", 0);
  117.    ForceNl();
  118.    flush_str();       /* flush string buffer to code list */
  119.    return ilc_base.next;
  120.    }
  121.  
  122. /*
  123.  * add_ptr - add another level of indirection to a declarator. Print it in
  124.  *   the output file and proceduce in-line C code.
  125.  */
  126. static novalue add_ptr(dcltor)
  127. struct node *dcltor;
  128.    {
  129.    while (dcltor->nd_id == ConCatNd) {
  130.       c_walk(dcltor->u[0].child, IndentInc, 0);
  131.       ilc_walk(dcltor->u[0].child, 0, 0);
  132.       dcltor = dcltor->u[1].child;
  133.       }
  134.    switch (dcltor->nd_id) {
  135.       case PrimryNd:
  136.          /*
  137.           * We have reached the name, add a level of indirection.
  138.           */
  139.          prt_str("(*", IndentInc);
  140.          ilc_str("(*");
  141.          prt_str(dcltor->tok->image, IndentInc);
  142.          ilc_str(dcltor->tok->image);
  143.          prt_str(")", IndentInc);
  144.          ilc_str(")");
  145.          break;
  146.       case PrefxNd:
  147.          /*
  148.           * (...)
  149.           */
  150.          prt_str("(", IndentInc);
  151.          ilc_str("(");
  152.          add_ptr(dcltor->u[0].child);
  153.          prt_str(")", IndentInc);
  154.          ilc_str(")");
  155.          break;
  156.       case BinryNd:
  157.          if (dcltor->tok->tok_id == ')') {
  158.             /*
  159.              * Function declaration. 
  160.              */
  161.             add_ptr(dcltor->u[0].child);
  162.             prt_str("(", IndentInc);
  163.             ilc_str("(");
  164.             c_walk(dcltor->u[1].child, IndentInc, 0);
  165.             ilc_walk(dcltor->u[1].child, 0, 0);
  166.             prt_str(")", IndentInc);
  167.             ilc_str(")");
  168.             }
  169.          else {
  170.             /*
  171.              * Array.
  172.              */
  173.             add_ptr(dcltor->u[0].child);
  174.             prt_str("[", IndentInc);
  175.             ilc_str("[");
  176.             c_walk(dcltor->u[1].child, IndentInc, 0);
  177.             ilc_walk(dcltor->u[1].child, 0, 0);
  178.             prt_str("]", IndentInc);
  179.             ilc_str("]");
  180.             }
  181.       }
  182.    }
  183.  
  184. /*
  185.  * bdy_prm - produce the code that must be be supplied as the argument
  186.  *  to the call of a body function.
  187.  */
  188. struct il_c *bdy_prm(addr_of, just_desc, sym, may_mod)
  189. int addr_of;
  190. int just_desc;
  191. struct sym_entry *sym;
  192. int may_mod;
  193.    {
  194.    init_ilc();              /* initialize code list and string buffer */
  195.    if (addr_of)
  196.       ilc_str("&(");                  /* call-by-reference parameter */
  197.    ilc_var(sym, just_desc, may_mod);  /* variable to pass as argument */
  198.    if (addr_of)
  199.       ilc_str(")");
  200.    flush_str();             /* flush string buffer to code list */
  201.    return ilc_base.next;
  202.    }
  203.  
  204. /*
  205.  * ilc_dcl - produce in-line code for a C declaration.
  206.  */
  207. struct il_c *ilc_dcl(tqual, dcltor, init)
  208. struct node *tqual;
  209. struct node *dcltor;
  210. struct node *init;
  211.    {
  212.    init_ilc();              /* initialize code list and string buffer */
  213.    ilc_walk(tqual, 0, 0);
  214.    ilc_str(" ");
  215.    ilc_walk(dcltor, 0, 0);
  216.    if (init != NULL) {
  217.       ilc_str(" = ");
  218.       ilc_walk(init, 0, 0);
  219.       }
  220.    ilc_str(";");
  221.    flush_str();             /* flush string buffer to code list */
  222.    return ilc_base.next;
  223.    }
  224.  
  225.  
  226. /*
  227.  *  init_ilc - initialize the code list by pointing to ilc_base. Initialize
  228.  *   the string buffer.
  229.  */
  230. static novalue init_ilc()
  231.    {
  232.    nxt_char = 0;
  233.    line_ref = NULL;
  234.    insert_nl = 0;
  235.    ilc_base.il_c_type = 0;
  236.    ilc_base.next = NULL;
  237.    ilc_cur = &ilc_base;
  238.    }
  239.  
  240.  
  241. /*
  242.  * - ilc_chnl - check for new-line.
  243.  */
  244. static novalue ilc_chnl(t)
  245. struct token *t;
  246.    {
  247.    /*
  248.     * See if this is a reasonable place to put a newline.
  249.     */
  250.    if (t->flag & LineChk) {
  251.       if (line_ref != NULL &&
  252.          (t->fname != line_ref->fname || t->line != line_ref->line))
  253.             insert_nl = 1;
  254.       line_ref = t;
  255.       }
  256.    }
  257.  
  258. /*
  259.  * ilc_tok - convert a token to its string representation, quoting it
  260.  *  if it is a string or character literal.
  261.  */
  262. static novalue ilc_tok(t)
  263. struct token *t;
  264.    {
  265.    char *s;
  266.  
  267.    ilc_chnl(t);
  268.    s = t->image;
  269.    switch (t->tok_id) {
  270.       case StrLit:
  271.          ilc_str("\"");
  272.          ilc_str(s);
  273.          ilc_str("\"");
  274.          break;
  275.       case LStrLit:
  276.          ilc_str("L\"");
  277.          ilc_str(s);
  278.          ilc_str("\"");
  279.          break;
  280.       case CharConst:
  281.          ilc_str("'");
  282.          ilc_str(s);
  283.          ilc_str("'");
  284.          break;
  285.       case LCharConst:
  286.          ilc_str("L'");
  287.          ilc_str(s);
  288.          ilc_str("'");
  289.          break;
  290.       default:
  291.          ilc_str(s);
  292.       }
  293.    }
  294.  
  295. /*
  296.  * ilc_str - append a string to the string buffer.
  297.  */
  298. static novalue ilc_str(s)
  299. char *s;
  300.    {
  301.    /*
  302.     * see if a new-line is needed before the string
  303.     */
  304.    if (insert_nl && (nxt_char == 0 || sbuf[nxt_char - 1] != '\n')) {
  305.       insert_nl = 0;
  306.       ilc_str("\n");
  307.       }
  308.  
  309.    /*
  310.     * Put the string in the buffer. If the buffer is full, flush it
  311.     *  to an element in the in-line code list.
  312.     */
  313.    while (*s != '\0') {
  314.       if (nxt_char >= SBufSz - 1)
  315.          insrt_str();
  316.       sbuf[nxt_char++] = *s++;
  317.       }
  318.    }
  319.  
  320. /*
  321.  * insrt_str - insert the string in the buffer into the list of in-line
  322.  *  code.
  323.  */
  324. static novalue insrt_str()
  325.    {
  326.    alloc_ilc(ILC_Str);
  327.    sbuf[nxt_char] = '\0';
  328.    ilc_cur->s = salloc(sbuf);
  329.    nxt_char = 0;
  330.    }
  331.  
  332. /*
  333.  * flush_str - if the string buffer is not empty, flush it to the list
  334.  *  of in-line code.
  335.  */
  336. static novalue flush_str()
  337.    {
  338.    if (insert_nl)
  339.       ilc_str("");
  340.    if (nxt_char != 0)
  341.       insrt_str();
  342.    }
  343.  
  344. /*
  345.  * new_ilc - create a new element for the list of in-line C code. This
  346.  *   is called for non-string elements. If necessary it flushes the
  347.  *   string buffer to another element first.
  348.  */
  349. static novalue new_ilc(il_c_type)
  350. int il_c_type;
  351.    {
  352.    flush_str();
  353.    alloc_ilc(il_c_type);
  354.    }
  355.  
  356. /*
  357.  * alloc_ilc - allocate a new element for the list of in-line C code
  358.  *   and add it to the list.
  359.  */
  360. static novalue alloc_ilc(il_c_type)
  361. int il_c_type;
  362.    {
  363.    int i;
  364.    ilc_cur->next = NewStruct(il_c);
  365.    ilc_cur = ilc_cur->next;
  366.    ilc_cur->next = NULL;
  367.    ilc_cur->il_c_type = il_c_type;
  368.    for (i = 0; i < 3; ++i)
  369.       ilc_cur->code[i] = NULL;
  370.    ilc_cur->n = 0;
  371.    ilc_cur->s = NULL;
  372.    }
  373.  
  374. /*
  375.  * sep_ilc - translate the syntax tree, n, (possibly surrounding it by
  376.  *  strings) into a sub-list of in-line C code, remove the sub-list from
  377.  *  the main list, and return it.
  378.  */
  379. static struct il_c *sep_ilc(s1, n, s2)
  380. char *s1;
  381. struct node *n;
  382. char *s2;
  383.    {
  384.    struct il_c *ilc;
  385.  
  386.    ilc = ilc_cur;     /* remember the starting point in the main list */
  387.    if (s1 != NULL)
  388.       ilc_str(s1);
  389.    ilc_walk(n, 0, 0);
  390.    if (s2 != NULL)
  391.       ilc_str(s2);
  392.    flush_str();
  393.  
  394.    /*
  395.     * Reset the main list to its condition upon entry, and return the sublist
  396.     *   created from s1, n, and s2.
  397.     */
  398.    ilc_cur = ilc;
  399.    ilc = ilc_cur->next;
  400.    ilc_cur->next = NULL;
  401.    return ilc;
  402.    }
  403.  
  404. /*
  405.  * ilc_var - create in-line C code for a variable in the symbol table.
  406.  */
  407. static novalue ilc_var(sym, just_desc, may_mod)
  408. struct sym_entry *sym;
  409. int just_desc;
  410. int may_mod;
  411.    {
  412.    if (sym->il_indx >= 0) {
  413.       /*
  414.        * This symbol will be in symbol table iconc builds from the
  415.        *   data base entry. iconc needs to know if this is a modifying
  416.        *   reference so it can perform optimizations. This is indicated by
  417.        *   may_mod. Some variables are implemented as the vword of a
  418.        *   descriptor. Sometime the entire descriptor must be accessed.
  419.        *   This is indicated by just_desc.
  420.        */
  421.       if (may_mod) {
  422.          new_ilc(ILC_Mod);
  423.          if (sym->id_type & DrfPrm)
  424.             sym->u.param_info.parm_mod |= 1;
  425.          }
  426.       else
  427.          new_ilc(ILC_Ref);
  428.       ilc_cur->n = sym->il_indx;
  429.       if (just_desc)
  430.          ilc_cur->s = "d";
  431.       }
  432.    else switch (sym->id_type) {
  433.       case TndDesc: 
  434.          /*
  435.           * variable declared: tended struct descrip ...
  436.           */
  437.          new_ilc(ILC_Tend);
  438.          ilc_cur->n = sym->t_indx;   /* index into tended variables */
  439.          break;
  440.       case TndStr:
  441.          /*
  442.           * variable declared: tended char *...
  443.           */
  444.          new_ilc(ILC_Tend);
  445.          ilc_cur->n = sym->t_indx;   /* index into tended variables */
  446.          ilc_str(".vword.sptr");     /* get string pointer from vword union */
  447.          break;
  448.       case TndBlk:
  449.          /*
  450.           * If blk_name field is null, this variable was declared:
  451.           *    tended union block *...
  452.           *  otherwise it was declared:
  453.           *    tended struct <blk_name> *...
  454.           */
  455.          if (sym->u.tnd_var.blk_name != NULL) {
  456.             /*
  457.              * Cast the "union block *" from the vword to the correct
  458.              *   struct pointer. This cast can be used as an r-value or
  459.              *   an l-value.
  460.              */
  461.             ilc_str("(*(struct ");
  462.             ilc_str(sym->u.tnd_var.blk_name);
  463.             ilc_str("**)&"); 
  464.             }
  465.          new_ilc(ILC_Tend);
  466.          ilc_cur->n = sym->t_indx;  /* index into tended variables */
  467.          ilc_str(".vword.bptr");    /* get block pointer from vword union */
  468.          if (sym->u.tnd_var.blk_name != NULL)
  469.             ilc_str(")");
  470.          break;
  471.       case RsltLoc:
  472.          /*
  473.           * This is the special variable for the result of the operation.
  474.           *  iconc needs to know if this is a modifying reference so it
  475.           *  can perform optimizations.
  476.           */
  477.          if (may_mod)
  478.             new_ilc(ILC_Mod);
  479.          else
  480.             new_ilc(ILC_Ref);
  481.          ilc_cur->n = RsltIndx;
  482.          break;
  483.       default:
  484.          /*
  485.           * This is a variable with an ordinary declaration. Access it by
  486.           *   its identifier.
  487.           */
  488.          ilc_str(sym->image);
  489.       }
  490.    }
  491.  
  492. /*
  493.  * ilc_walk - walk the syntax tree for C code producing a list of "in-line"
  494.  *   code. This function needs to know if the code is in a modifying context,
  495.  *   such as the left-hand-side of an assignment.
  496.  */
  497. static novalue ilc_walk(n, may_mod, const_cast)
  498. struct node *n;
  499. int may_mod;
  500. int const_cast;
  501.    {
  502.    struct token *t;
  503.    struct node *n1;
  504.    struct node *n2;
  505.    struct sym_entry *sym;
  506.    word cont_sav;
  507.    word brk_sav;
  508.    word l1, l2;
  509.    int typcd;
  510.  
  511.    if (n == NULL)
  512.       return;
  513.  
  514.    t =  n->tok;
  515.  
  516.    switch (n->nd_id) {
  517.       case PrimryNd:
  518.          /*
  519.           * Primary expressions consisting of a single token.
  520.           */
  521.          switch (t->tok_id) {
  522.             case Fail:
  523.                /*
  524.                 * fail statement. Note that this operaion can fail, output
  525.                 *   the corresponding "in-line" code, and make sure we have
  526.                 *   seen an abstract clause of some kind.
  527.                 */
  528.                cur_impl->ret_flag |= DoesFail;
  529.                insert_nl = 1;
  530.                new_ilc(ILC_Fail);
  531.                insert_nl = 1;
  532.                line_ref = NULL;
  533.                chkabsret(t, SomeType);
  534.                break;
  535.             case Errorfail:
  536.                /*
  537.                 * errorfail statement. Note that this operaion can do error
  538.                 *   conversion and output the corresponding "in-line" code.
  539.                 */
  540.                cur_impl->ret_flag |= DoesEFail;
  541.                insert_nl = 1;
  542.                new_ilc(ILC_EFail);
  543.                insert_nl = 1;
  544.                line_ref = NULL;
  545.                break;
  546.             case Break:
  547.                /*
  548.                 * iconc can only handle gotos for transfer of control in
  549.                 *  in-line code. A break label has been established for
  550.                 *  the current loop; transform the "break" into a goto.
  551.                 */
  552.                ilc_goto(brk_lbl);
  553.                break;
  554.             case Continue:
  555.                /*
  556.                 * iconc can only handle gotos for transfer of control in
  557.                 *  in-line code. A continue label has been established for
  558.                 *  the current loop; transform the "continue" into a goto.
  559.                 */
  560.                ilc_goto(cont_lbl);
  561.                break;
  562.             default:
  563.                /*
  564.                 * No special processing is needed for this primary
  565.                 *  expression, just output the image of the token.
  566.                 */
  567.                ilc_tok(t);
  568.             }
  569.          break;
  570.       case PrefxNd:
  571.          /*
  572.           * Expressions with one operand that are introduced by a token.
  573.           *  Note, "default :" does not appear here because switch
  574.           *  statements are not allowed in in-line code.
  575.           */
  576.          switch (t->tok_id) {
  577.             case Sizeof:
  578.                /*
  579.                 * sizeof(...)
  580.                 */
  581.                ilc_tok(t);
  582.                ilc_str("(");
  583.                ilc_walk(n->u[0].child, 0, 0);
  584.                ilc_str(")");
  585.                break;
  586.             case '{':
  587.                /*
  588.                 * initializer: { ... }
  589.                 */
  590.                ilc_tok(t);
  591.                ilc_walk(n->u[0].child, 0, 0);
  592.                ilc_str("}");
  593.                break;
  594.             case Goto:
  595.                /*
  596.                 * goto <label>;
  597.                 */
  598.                ilc_goto(n->u[0].child->u[0].sym->u.lbl_num);
  599.                break;
  600.             case Return:
  601.                /*
  602.                 * return <expression>;
  603.                 *  Indicate that this operation can return, then perform
  604.                 *  processing to categorize the kind of return statement
  605.                 *  and produce appropriate in-line code.
  606.                 */
  607.                cur_impl->ret_flag |= DoesRet;
  608.                ilc_ret(t, ILC_Ret, n->u[0].child);
  609.                break;
  610.             case Suspend:
  611.                /*
  612.                 * suspend <expression>;
  613.                 *  Indicate that this operation can suspend, then perform
  614.                 *  processing to categorize the kind of suspend statement
  615.                 *  and produce appropriate in-line code.
  616.                 */
  617.                cur_impl->ret_flag |= DoesSusp;
  618.                ilc_ret(t, ILC_Susp, n->u[0].child);
  619.                break;
  620.             case '(':
  621.                /*
  622.                 * ( ... )
  623.                 */
  624.                ilc_tok(t);
  625.                ilc_walk(n->u[0].child, may_mod, const_cast);
  626.                ilc_str(")");
  627.                break;
  628.             case Incr:
  629.             case Decr:
  630.                /*
  631.                 * The operand might be modified, otherwise nothing special
  632.                 *   is needed.
  633.                 */
  634.                ilc_tok(t);
  635.                ilc_walk(n->u[0].child, 1, 0);
  636.                break;
  637.             case '&':
  638.                /*
  639.                 * Unless the address is cast to a const pointer, this
  640.                 *  might be a modifiying reference.
  641.                 */
  642.                ilc_tok(t);
  643.                if (const_cast)
  644.                   ilc_walk(n->u[0].child, 0, 0);
  645.                else
  646.                   ilc_walk(n->u[0].child, 1, 0);
  647.                break;
  648.             default:
  649.                /*
  650.                 * Nothing special is needed, just output the image of
  651.                 *   the prefix operation followed by its operand.
  652.                 */
  653.                ilc_tok(t);
  654.                ilc_walk(n->u[0].child, 0, 0);
  655.             }
  656.          break;
  657.       case PstfxNd:
  658.          /*
  659.           * postfix notation: ';', '++', and '--'. The later two
  660.           *   modify their operands.
  661.           */
  662.          if (t->tok_id == ';')
  663.             ilc_walk(n->u[0].child, 0, 0);
  664.          else
  665.             ilc_walk(n->u[0].child, 1, 0);
  666.          ilc_tok(t);
  667.          break;
  668.       case PreSpcNd:
  669.          /*
  670.           * Prefix notation that needs a space after the expression;
  671.           *   used for pointer/type qualifier lists.
  672.           */
  673.          ilc_tok(t);
  674.          ilc_walk(n->u[0].child, 0, 0);
  675.          ilc_str(" ");
  676.          break;
  677.       case SymNd:
  678.          /*
  679.           * Identifier in symbol table. See if it start a new line. Note
  680.           *   that we need to know whether this is a modifying reference.
  681.           */
  682.          ilc_chnl(n->tok);
  683.          ilc_var(n->u[0].sym, 0, may_mod);
  684.          break;
  685.       case BinryNd:
  686.          switch (t->tok_id) {
  687.             case '[':
  688.                /*
  689.                 * Expression or declaration:
  690.                 *   <expr1> [ <expr2> ]
  691.                 */
  692.                ilc_walk(n->u[0].child, may_mod, 0);
  693.                ilc_str("[");
  694.                ilc_walk(n->u[1].child, 0, 0);
  695.                ilc_str("]");
  696.                break;
  697.             case '(':
  698.                /*
  699.                 * ( <type> ) expr
  700.                 */
  701.                ilc_tok(t);
  702.                ilc_walk(n->u[0].child, 0, 0);
  703.                ilc_str(")");
  704.                /*
  705.                 * See if the is a const cast.
  706.                 */
  707.                for (n1 = n->u[0].child; n1->nd_id == LstNd; n1 = n1->u[0].child)
  708.                   ;
  709.                if (n1->nd_id == PrimryNd && n1->tok->tok_id == Const)
  710.                   ilc_walk(n->u[1].child, 0, 1);
  711.                else
  712.                   ilc_walk(n->u[1].child, 0, 0);
  713.                break;
  714.             case ')':
  715.                /*
  716.                 * Expression or declaration:
  717.                 *   <expr> ( <arg-list> )
  718.                 */
  719.                ilc_walk(n->u[0].child, 0, 0);
  720.                ilc_str("(");
  721.                ilc_walk(n->u[1].child, 0, 0);
  722.                ilc_tok(t);
  723.                break;
  724.             case Struct:
  725.             case Union:
  726.             case Enum:
  727.                /*
  728.                 * <struct-union-enum> <identifier>
  729.                 * <struct-union-enum> { <component-list> }
  730.                 * <struct-union-enum> <identifier> { <component-list> }
  731.                 */
  732.                ilc_tok(t);
  733.                ilc_str(" ");
  734.                ilc_walk(n->u[0].child, 0, 0);
  735.                if (n->u[1].child != NULL) {
  736.                   ilc_str(" {");
  737.                   ilc_walk(n->u[1].child, 0, 0);
  738.                   ilc_str("}");
  739.                   }
  740.                break;
  741.             case ';':
  742.                /*
  743.                 * <type specifiers> <declarator> ;
  744.                 */
  745.                ilc_walk(n->u[0].child, 0, 0);
  746.                ilc_str(" ");
  747.                ilc_walk(n->u[1].child, 0, 0);
  748.                ilc_tok(t);
  749.                break;
  750.             case ':':
  751.                /*
  752.                 * <label> : <statement>
  753.                 */
  754.                ilc_lbl(n->u[0].child->u[0].sym->u.lbl_num);
  755.                ilc_walk(n->u[1].child, 0, 0);
  756.                break;
  757.             case Switch:
  758.                errt1(t, "switch statement not supported in in-line code");
  759.                break;
  760.             case While:
  761.                /*
  762.                 * Convert "while (c) s" into [conditional] gotos and labels.
  763.                 *   Establish labels for break and continue statements
  764.                 *   within s.
  765.                 */
  766.                brk_sav = brk_lbl;
  767.                cont_sav = cont_lbl;
  768.                cont_lbl = lbl_num++;
  769.                brk_lbl = lbl_num++;
  770.                ilc_lbl(cont_lbl);                      /* L1: */
  771.                ilc_cgoto(1, n->u[0].child, brk_lbl);   /* if (!(c)) goto L2; */
  772.                ilc_walk(n->u[1].child, 0, 0);          /* s */
  773.                ilc_goto(cont_lbl);                     /* goto L1; */
  774.                ilc_lbl(brk_lbl);                       /* L2: */
  775.                brk_lbl = brk_sav;
  776.                cont_lbl = cont_sav;
  777.                break;
  778.             case Do:
  779.                /*
  780.                 * Convert "do s while (c);" loop into a conditional goto and
  781.                 *  label. Establish labels for break and continue statements
  782.                 *  within s.
  783.                 */ 
  784.                brk_sav = brk_lbl;
  785.                cont_sav = cont_lbl;
  786.                cont_lbl = lbl_num++;
  787.                brk_lbl = lbl_num++;
  788.                ilc_lbl(cont_lbl);                        /* L1: */
  789.                ilc_walk(n->u[0].child, 0, 0);            /* s */
  790.                ilc_cgoto(0, n->u[1].child, cont_lbl);    /* if (c) goto L1 */
  791.                ilc_lbl(brk_lbl);
  792.                brk_lbl = brk_sav;
  793.                cont_lbl = cont_sav;
  794.                break;
  795.             case '.':
  796.                /*
  797.                 * <expr1> . <expr2>
  798.                 */
  799.                ilc_walk(n->u[0].child, may_mod, 0);
  800.                ilc_tok(t);
  801.                ilc_walk(n->u[1].child, 0, 0);
  802.                break;
  803.             case Arrow:
  804.                /*
  805.                 * <expr1> -> <expr2>
  806.                 */
  807.                ilc_walk(n->u[0].child, 0, 0);
  808.                ilc_tok(t);
  809.                ilc_walk(n->u[1].child, 0, 0);
  810.                break;
  811.             case Runerr:
  812.                /*
  813.                 * runerr ( <expr> ) ;
  814.                 * runerr ( <expr> , <expr> ) ;
  815.                 */
  816.                ilc_str("err_msg(");
  817.                ilc_walk(n->u[0].child, 0, 0);
  818.                if (n->u[1].child == NULL)
  819.                   ilc_str(", NULL);");
  820.                else {
  821.                   ilc_str(", &(");
  822.                   ilc_walk(n->u[1].child, 0, 0);
  823.                   ilc_str("));");
  824.                   }
  825.                /*
  826.                 * Handle error conversion.
  827.                 */
  828.                cur_impl->ret_flag |= DoesEFail;
  829.                insert_nl = 1;
  830.                new_ilc(ILC_EFail);
  831.                insert_nl = 1;
  832.                break;
  833.             case Is:
  834.                /*
  835.                 * is : <type-name> ( <expr> )
  836.                 */
  837.                typcd = icn_typ(n->u[0].child);
  838.                n1 =  n->u[1].child;
  839.                if (typcd == str_typ) {
  840.                   ilc_str("(!((");
  841.                   ilc_walk(n1, 0, 0);
  842.                   ilc_str(").dword & F_Nqual))");
  843.                   }
  844.                else if (typcd == Variable) {
  845.                   ilc_str("(((");
  846.                   ilc_walk(n1, 0, 0);
  847.                   ilc_str(").dword & D_Var) == D_Var)");
  848.                   }
  849.               else if (typcd == int_typ) {
  850.                   ForceNl();
  851.                   prt_str("#ifdef LargeInts", 0);
  852.                   ForceNl();
  853.  
  854.                   ilc_str("(((");
  855.                   ilc_walk(n1, 0, 0);
  856.                   ilc_str(").dword == D_Integer) || ((");
  857.                   ilc_walk(n1, 0, 0);
  858.                   ilc_str(").dword == D_Lrgint))");
  859.  
  860.                   ForceNl();
  861.                   prt_str("#else /* LargeInts */", 0);
  862.                   ForceNl();
  863.  
  864.                   ilc_str("((");
  865.                   ilc_walk(n1, 0, 0);
  866.                   ilc_str(").dword == D_Integer)");
  867.  
  868.                   ForceNl();
  869.                   prt_str("#endif /* LargeInts */", 0);
  870.                   ForceNl();
  871.                   }
  872.               else {
  873.                   ilc_str("((");
  874.                   ilc_walk(n1, 0, 0);
  875.                   ilc_str(").dword == D_");
  876.                   ilc_str(typ_name(typcd, n->u[0].child->tok));
  877.                   ilc_str(")");
  878.                   }
  879.                break;
  880.             case '=':
  881.             case MultAsgn:
  882.             case DivAsgn:
  883.             case ModAsgn:
  884.             case PlusAsgn:
  885.             case MinusAsgn:
  886.             case LShftAsgn:
  887.             case RShftAsgn:
  888.             case AndAsgn:
  889.             case XorAsgn:
  890.             case OrAsgn:
  891.                /*
  892.                 * Assignment operation (or initialization or specification
  893.                 *   of enumeration value). Left-hand-side may be modified.
  894.                 */
  895.                ilc_walk(n->u[0].child, 1, 0);
  896.                ilc_str(" ");
  897.                ilc_tok(t);
  898.                ilc_str(" ");
  899.                ilc_walk(n->u[1].child, 0, 0);
  900.                break;
  901.             default:
  902.                /*
  903.                 * Simple binary operator. Nothing special is needed,
  904.                 *   just put space around the operator.
  905.                 */
  906.                ilc_walk(n->u[0].child, 0, 0);
  907.                ilc_str(" ");
  908.                ilc_tok(t);
  909.                ilc_str(" ");
  910.                ilc_walk(n->u[1].child, 0, 0);
  911.                break;
  912.             }
  913.          break;
  914.       case LstNd:
  915.          /*
  916.           * Consecutive expressions that need a space between them.
  917.           */
  918.          ilc_walk(n->u[0].child, 0, 0);
  919.          ilc_str(" ");
  920.          ilc_walk(n->u[1].child, 0, 0);
  921.          break;
  922.       case ConCatNd:
  923.          /*
  924.           * Consecutive expressions that don't need space between them.
  925.           */
  926.          ilc_walk(n->u[0].child, 0, 0);
  927.          ilc_walk(n->u[1].child, 0, 0);
  928.          break;
  929.       case CommaNd:
  930.          ilc_walk(n->u[0].child, 0, 0);
  931.          ilc_tok(t);
  932.          ilc_str(" ");
  933.          ilc_walk(n->u[1].child, 0, 0);
  934.          break;
  935.       case StrDclNd:
  936.          /*
  937.           * struct field declarator. May be a bit field.
  938.           */
  939.          ilc_walk(n->u[0].child, 0, 0);
  940.          if (n->u[1].child != NULL) {
  941.             ilc_str(": ");
  942.             ilc_walk(n->u[1].child, 0, 0);
  943.             }
  944.          break;
  945.       case CompNd: {
  946.          /*
  947.           * Compound statement. May have declarations including tended
  948.           *   declarations that are separated out.
  949.           */
  950.          struct node *dcls;
  951.  
  952.          /*
  953.           * If the in-line code has declarations, the block must
  954.           *   be surrounded by braces. Braces are special constructs
  955.           *   because iconc must not delete one without the other
  956.           *   during code optimization.
  957.           */
  958.          dcls = n->u[0].child;
  959.          if (dcls != NULL) {
  960.             insert_nl = 1;
  961.             new_ilc(ILC_LBrc);
  962.             insert_nl = 1;
  963.             line_ref = NULL;
  964.             ilc_walk(dcls, 0, 0);
  965.             }
  966.          /*
  967.           * we are in an inner block. tended locations may need to
  968.           *  be set to values from declaration initializations.
  969.           */
  970.          for (sym = n->u[1].sym; sym!= NULL; sym = sym->u.tnd_var.next) {
  971.             if (sym->u.tnd_var.init != NULL) {
  972.                new_ilc(ILC_Tend);
  973.                ilc_cur->n = sym->t_indx;
  974.  
  975.                /*
  976.                 * See if the variable is just the vword of the descriptor.
  977.                 */
  978.                switch (sym->id_type) {
  979.                   case TndDesc:
  980.                      ilc_str(" = ");
  981.                      break;
  982.                   case TndStr:
  983.                      ilc_str(".vword.sptr = ");
  984.                      break;
  985.                   case TndBlk:
  986.                      ilc_str(".vword.bptr = (union block *)");
  987.                      break;
  988.                   }
  989.                ilc_walk(sym->u.tnd_var.init, 0, 0);  /* initial value */
  990.                ilc_str(";");
  991.                }
  992.             }
  993.  
  994.          ilc_walk(n->u[2].child, 0, 0); /* body of compound statement */
  995.  
  996.          if (dcls != NULL) {
  997.             insert_nl = 1;
  998.             new_ilc(ILC_RBrc);  /* closing brace */
  999.             insert_nl = 1;
  1000.             line_ref = NULL;
  1001.             }
  1002.          }
  1003.          break;
  1004.       case TrnryNd:
  1005.          switch (t->tok_id) {
  1006.             case '?':
  1007.                /*
  1008.                 * <expr> ? <expr> : <expr>
  1009.                 */
  1010.                ilc_walk(n->u[0].child, 0, 0);
  1011.                ilc_str(" ");
  1012.                ilc_tok(t);
  1013.                ilc_str(" ");
  1014.                ilc_walk(n->u[1].child, 0, 0);
  1015.                ilc_str(" : ");
  1016.                ilc_walk(n->u[2].child, 0, 0);
  1017.                break;
  1018.             case If:
  1019.                /*
  1020.                 * Convert if statement into [conditional] gotos and labels.
  1021.                 */
  1022.                n1 = n->u[1].child;
  1023.                n2 = n->u[2].child;
  1024.                l1 = lbl_num++;
  1025.                if (n2 == NULL) {    /* if (c) then s */
  1026.                   ilc_cgoto(1, n->u[0].child, l1);      /* if (!(c)) goto L1; */
  1027.                   ilc_walk(n1, 0, 0);                   /* s */
  1028.                   ilc_lbl(l1);                          /* L1: */
  1029.                   }
  1030.                else {               /* if (c) then s1 else s2 */
  1031.                   ilc_cgoto(0, n->u[0].child, l1);      /* if (c) goto L1; */
  1032.                   ilc_walk(n2, 0, 0);                   /* s2 */
  1033.                   l2 = lbl_num++;
  1034.                   ilc_goto(l2);                         /* goto L2; */
  1035.                   ilc_lbl(l1);                          /* L1: */
  1036.                   ilc_walk(n1, 0, 0);                   /* s1 */
  1037.                   ilc_lbl(l2);                          /* L2: */
  1038.                   }
  1039.                break;
  1040.             case Type_case:
  1041.                errt1(t, "type case statement not supported in in-line code");
  1042.                break;
  1043.             case Cnv:
  1044.                /*
  1045.                 * cnv : <type> ( <expr> , <expr> )
  1046.                 */
  1047.                ilc_cnv(n->u[0].child, n->u[1].child, NULL, n->u[2].child);
  1048.                break;
  1049.             }
  1050.          break;
  1051.       case QuadNd:
  1052.          switch (t->tok_id) {
  1053.             case For:
  1054.                /*
  1055.                 * convert "for (e1; e2; e3) s" into [conditional] gotos and
  1056.                 *  labels.
  1057.                 */
  1058.                brk_sav = brk_lbl;
  1059.                cont_sav = cont_lbl;
  1060.                l1 = lbl_num++;
  1061.                cont_lbl = lbl_num++;
  1062.                brk_lbl = lbl_num++;
  1063.                ilc_walk(n->u[0].child, 0, 0);     /* e1; */
  1064.                ilc_str(";");
  1065.                ilc_lbl(l1);                       /* L1: */
  1066.                n2 = n->u[1].child;
  1067.                if (n2 != NULL)
  1068.                   ilc_cgoto(1, n2, brk_lbl);      /* if (!(e2)) goto L2; */
  1069.                ilc_walk(n->u[3].child, 0, 0);     /* s */
  1070.                ilc_lbl(cont_lbl);
  1071.                ilc_walk(n->u[2].child, 0, 0);     /* e3; */
  1072.                ilc_str(";");
  1073.                ilc_goto(l1);                      /* goto L1 */
  1074.                ilc_lbl(brk_lbl);                  /* L2: */
  1075.                brk_lbl = brk_sav;
  1076.                cont_lbl = cont_sav;
  1077.                break;
  1078.             case Def:
  1079.                ilc_cnv(n->u[0].child, n->u[1].child, n->u[2].child,
  1080.                   n->u[3].child);
  1081.                break;
  1082.             }
  1083.          break;
  1084.       }
  1085.    }
  1086.  
  1087. /*
  1088.  * ilc_cnv - produce code for a cnv: or def: statement.
  1089.  */
  1090. static novalue ilc_cnv(cnv_typ, src, dflt, dest)
  1091. struct node *cnv_typ;
  1092. struct node *src;
  1093. struct node *dflt;
  1094. struct node *dest;
  1095.    {
  1096.    int dflt_to_ptr;
  1097.    int typcd;
  1098.  
  1099.    /*
  1100.     * Get the name of the conversion routine for the given type
  1101.     *  and determine whether the conversion routine needs a
  1102.     *  pointer to the default value (if there is one) rather
  1103.     *  the the value itself.
  1104.     */
  1105.    typcd = icn_typ(cnv_typ);
  1106.    ilc_str(cnv_name(typcd, dflt, &dflt_to_ptr));
  1107.    ilc_str("(");
  1108.  
  1109.    /*
  1110.     * If this is a conversion to a temporary string or cset, the
  1111.     *  conversion routine needs a temporary buffer in which to
  1112.     *  perform the conversion.
  1113.     */
  1114.    switch (typcd) {
  1115.       case TypTStr:
  1116.          new_ilc(ILC_SBuf);
  1117.          ilc_str(", ");
  1118.          break;
  1119.       case TypTCset:
  1120.          new_ilc(ILC_CBuf);
  1121.          ilc_str(", ");
  1122.          break;
  1123.       }
  1124.  
  1125.    /*
  1126.     * Produce code for the source expression.
  1127.     */
  1128.    ilc_str("&(");
  1129.    ilc_walk(src, 0, 0);
  1130.    ilc_str("), ");
  1131.  
  1132.    /*
  1133.     * Produce code for the default expression, if there is one.
  1134.     */
  1135.    if (dflt != NULL) {
  1136.       if (dflt_to_ptr)
  1137.          ilc_str("&(");
  1138.       ilc_walk(dflt, 0, 0);
  1139.       if (dflt_to_ptr)
  1140.          ilc_str("), ");
  1141.       else
  1142.          ilc_str(", ");
  1143.       }
  1144.  
  1145.    /*
  1146.     * Produce code for the destination expression.
  1147.     */
  1148.    ilc_str("&(");
  1149.    ilc_walk(dest, 1, 0);
  1150.    ilc_str("))");
  1151.    }
  1152.  
  1153. /*
  1154.  * ilc_ret - produce in-line code for suspend/return statement.
  1155.  */
  1156. static novalue ilc_ret(t, ilc_typ, n)
  1157. struct token *t;
  1158. int ilc_typ;
  1159. struct node *n;
  1160.    {
  1161.    struct node *caller;
  1162.    struct node *args;
  1163.    int typcd;
  1164.  
  1165.    insert_nl = 1;
  1166.    line_ref = NULL;
  1167.    new_ilc(ilc_typ);
  1168.  
  1169.    if (n->nd_id == SymNd && n->u[0].sym->id_type == RsltLoc) {
  1170.       /*
  1171.        * return/suspend result;
  1172.        */
  1173.       ilc_cur->n = RetNone;
  1174.       return;
  1175.       }
  1176.  
  1177.    if (n->nd_id == PrefxNd && n->tok != NULL) {
  1178.       switch (n->tok->tok_id) {
  1179.          case C_Integer:
  1180.             /*
  1181.              * return/suspend C_integer <expr>;
  1182.              */
  1183.             ilc_cur->n = TypCInt;
  1184.             ilc_cur->code[0] = sep_ilc(NULL, n->u[0].child, NULL);
  1185.             chkabsret(t, int_typ);
  1186.             return;
  1187.          case C_Double:
  1188.             /*
  1189.              * return/suspend C_double <expr>;
  1190.              */
  1191.             ilc_cur->n = TypCDbl;
  1192.             ilc_cur->code[0] = sep_ilc(NULL, n->u[0].child, NULL);
  1193.             chkabsret(t, real_typ);
  1194.             return;
  1195.          case C_String:
  1196.             /*
  1197.              * return/suspend C_string <expr>;
  1198.              */
  1199.             ilc_cur->n = TypCStr;
  1200.             ilc_cur->code[0] = sep_ilc(NULL, n->u[0].child, NULL);
  1201.             chkabsret(t, str_typ);
  1202.             return;
  1203.          }
  1204.       }
  1205.    else if (n->nd_id == BinryNd && n->tok->tok_id == ')') {
  1206.       /*
  1207.        * Return value is in form of function call, see if it is really
  1208.        *  a descriptor constructor.
  1209.        */
  1210.       caller = n->u[0].child;
  1211.       args = n->u[1].child;
  1212.       if (caller->nd_id == SymNd) {
  1213.          switch (caller->tok->tok_id) {
  1214.             case IconType:
  1215.                typcd = caller->u[0].sym->u.typ_indx;
  1216.                ilc_cur->n = typcd;
  1217.                switch (icontypes[typcd].rtl_ret) {
  1218.                   case TRetBlkP:
  1219.                   case TRetDescP:
  1220.                   case TRetCharP:
  1221.                   case TRetCInt:
  1222.                      /*
  1223.                       * return/suspend <type>(<value>);
  1224.                       */
  1225.                      ilc_cur->code[0] = sep_ilc(NULL, args, NULL);
  1226.                      break;
  1227.                   case TRetSpcl:
  1228.                      if (typcd == str_typ) {
  1229.                         /*
  1230.                          * return/suspend string(<len>, <char-pntr>);
  1231.                          */
  1232.                         ilc_cur->code[0] = sep_ilc(NULL, args->u[0].child,NULL);
  1233.                         ilc_cur->code[1] = sep_ilc(NULL, args->u[1].child,NULL);
  1234.                         }
  1235.                      else if (typcd == stv_typ) {
  1236.                         /*
  1237.                          * return/suspend tvsubs(<desc-pntr>, <start>, <len>);
  1238.                          */
  1239.                         ilc_cur->n = stv_typ;
  1240.                         ilc_cur->code[0] = sep_ilc(NULL,
  1241.                             args->u[0].child->u[0].child, NULL);
  1242.                         ilc_cur->code[1] = sep_ilc(NULL,
  1243.                             args->u[0].child->u[1].child, NULL);
  1244.                         ilc_cur->code[2] = sep_ilc(NULL, args->u[1].child,
  1245.                             NULL);
  1246.                         chkabsret(t, stv_typ);
  1247.                                  }
  1248.                      break;
  1249.                   }
  1250.                chkabsret(t, typcd);
  1251.                return;
  1252.             case Named_var:
  1253.                /*
  1254.                 * return/suspend named_var(<desc-pntr>);
  1255.                 */
  1256.                ilc_cur->n = RetNVar;
  1257.                ilc_cur->code[0] = sep_ilc(NULL, args, NULL);
  1258.                chkabsret(t, TypVar);
  1259.                return;
  1260.             case Struct_var:
  1261.                /*
  1262.                 * return/suspend struct_var(<desc-pntr>, <block_pntr>);
  1263.                 */
  1264.                ilc_cur->n = RetSVar;
  1265.                ilc_cur->code[0] = sep_ilc(NULL, args->u[0].child, NULL);
  1266.                ilc_cur->code[1] = sep_ilc(NULL, args->u[1].child, NULL);
  1267.                chkabsret(t, TypVar);
  1268.                return;
  1269.             }
  1270.          }
  1271.       }
  1272.  
  1273.    /*
  1274.     * If it is not one of the special returns, it is just a return of
  1275.     *  a descriptor.
  1276.     */
  1277.    ilc_cur->n = RetDesc;
  1278.    ilc_cur->code[0] = sep_ilc(NULL, n, NULL);
  1279.    chkabsret(t, SomeType);
  1280.    }
  1281.  
  1282. /*
  1283.  * ilc_goto - produce in-line C code for a goto to a numbered label.
  1284.  */
  1285. static novalue ilc_goto(lbl)
  1286. word lbl;
  1287.    {
  1288.    insert_nl = 1;
  1289.    new_ilc(ILC_Goto);
  1290.    ilc_cur->n = lbl;
  1291.    insert_nl = 1;
  1292.    line_ref = NULL;
  1293.    }
  1294.  
  1295. /*
  1296.  * ilc_cgoto - produce in-line C code for a conditional goto to a numbered
  1297.  *  label. The condition may be negated.
  1298.  */
  1299. static novalue ilc_cgoto(neg, cond, lbl)
  1300. int neg;
  1301. struct node *cond;
  1302. word lbl;
  1303.    {
  1304.    insert_nl = 1;
  1305.    line_ref = NULL;
  1306.    new_ilc(ILC_CGto);
  1307.    if (neg)
  1308.       ilc_cur->code[0] = sep_ilc("!(", cond, ")");
  1309.    else
  1310.       ilc_cur->code[0] = sep_ilc(NULL, cond, NULL);
  1311.    ilc_cur->n = lbl;
  1312.    insert_nl = 1;
  1313.    line_ref = NULL;
  1314.    }
  1315.  
  1316. /*
  1317.  * ilc_lbl - produce in-line C code for a numbered label.
  1318.  */
  1319. static novalue ilc_lbl(lbl)
  1320. word lbl;
  1321.    {
  1322.    insert_nl = 1;
  1323.    new_ilc(ILC_Lbl);
  1324.    ilc_cur->n = lbl;
  1325.    insert_nl = 1;
  1326.    line_ref = NULL;
  1327.    }
  1328. #endif                    /* Rttx */
  1329.  
  1330. /*
  1331.  * chkabsret - make sure a previous abstract return statement
  1332.  *  was encountered and that it is consistent with this return,
  1333.  *  suspend, or fail.
  1334.  */
  1335. novalue chkabsret(tok, ret_typ)
  1336. struct token *tok;
  1337. int ret_typ;
  1338.    {
  1339.    if (abs_ret == NoAbstr)
  1340.       errt2(tok, tok->image, " with no preceding abstract return");
  1341.  
  1342.    /*
  1343.     * We only check for type consistency when it is easy, otherwise
  1344.     *   we don't bother.
  1345.     */
  1346.    if (abs_ret == SomeType || ret_typ == SomeType || abs_ret == TypAny)
  1347.       return;
  1348.  
  1349.    /*
  1350.     * Some return types match the generic "variable" type.
  1351.     */
  1352.    if (abs_ret == TypVar && ret_typ >= 0 && icontypes[ret_typ].deref != DrfNone)
  1353.       return;
  1354.  
  1355.    /*
  1356.     * Otherwise the abstract return must match the real one.
  1357.     */
  1358.    if (abs_ret != ret_typ)
  1359.       errt2(tok, tok->image,  " is inconsistent with abstract return");
  1360.    }
  1361.  
  1362. /*
  1363.  * just_type - strip non-type information from a type-qualifier list. Print
  1364.  *   it in the output file and if ilc is set, produce in-line C code.
  1365.  */
  1366. novalue just_type(typ, indent, ilc)
  1367. struct node *typ;
  1368. int indent;
  1369. int ilc;
  1370.    {
  1371.    if (typ->nd_id == LstNd) {
  1372.       /*
  1373.        * Simple list of type-qualifier elements - concatenate them.
  1374.        */
  1375.       just_type(typ->u[0].child, indent, ilc); 
  1376.       just_type(typ->u[1].child, indent, ilc);
  1377.       }
  1378.    else if (typ->nd_id == PrimryNd) {
  1379.       switch (typ->tok->tok_id) {
  1380.          case Typedef:
  1381.          case Extern:
  1382.          case Static:
  1383.          case Auto:
  1384.          case Register:
  1385.          case Const:
  1386.          case Volatile:
  1387.             return;         /* Don't output these declaration elements */
  1388.          default:
  1389.             c_walk(typ, indent, 0);
  1390. #ifndef Rttx
  1391.             if (ilc)
  1392.                ilc_walk(typ, 0, 0);
  1393. #endif                    /* Rttx */
  1394.          }
  1395.       }
  1396.    else {
  1397.       c_walk(typ, indent, 0);
  1398. #ifndef Rttx
  1399.       if (ilc)
  1400.          ilc_walk(typ, 0, 0);
  1401. #endif                    /* Rttx */
  1402.       }
  1403.    }
  1404.