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