home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Icon 8.1 / msm-1 / rtt.sit / rttout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-19  |  117.5 KB  |  3,820 lines  |  [TEXT/MPS ]

  1. #include "rtt.h"
  2.  
  3. #define NotId 0  /* declarator is not simple identifier */
  4. #define IsId  1  /* declarator is simple identifier */
  5.  
  6. #define OrdFunc -1   /* indicates ordinary C function - non-token value */
  7.  
  8. /*
  9.  * VArgAlwnc - allowance for the variable part of an argument list in the
  10.  *  most general version of an operation. If it is too small, storage must
  11.  *  be malloced. 3 was chosen because over 90 percent of all writes have
  12.  *  3 or fewer arguments. It is possible that 4 would be a better number,
  13.  *  but 5 is probably overkill.
  14.  */
  15. #define VArgAlwnc 3
  16.  
  17. /*
  18.  * Prototypes for static functions.
  19.  */
  20. hidden novalue cnv_fnc       Params((struct token *t, int typcd,
  21.                                struct node *src, struct node *dflt,
  22.                                struct node *dest, int indent));
  23. hidden novalue chk_conj      Params((struct node *n));
  24. hidden novalue chk_nl        Params((int indent));
  25. hidden novalue chk_rsltblk   Params((int indent));
  26. hidden novalue comp_def      Params((struct node *n));
  27. hidden int     does_call     Params((struct node *expr));
  28. hidden novalue failure       Params((int indent, int brace));
  29. hidden novalue interp_def    Params((struct node *n));
  30. hidden int     len_sel       Params((struct node *sel,
  31.                                struct parminfo *strt_prms,
  32.                                struct parminfo *end_prms, int indent));
  33. hidden novalue line_dir      Params((int nxt_line, char *new_fname));
  34. hidden int     only_proto    Params((struct node *n));
  35. hidden novalue parm_locs     Params((struct sym_entry *op_params));
  36. hidden novalue parm_tnd      Params((struct sym_entry *sym));
  37. hidden novalue prt_runerr    Params((struct token *t, struct node *num,
  38.                                struct node *val, int indent));
  39. hidden novalue prt_tok       Params((struct token *t, int indent));
  40. hidden novalue prt_var       Params((struct node *n, int indent));
  41. hidden int     real_def      Params((struct node *n));
  42. hidden int     retval_dcltor Params((struct node *dcltor, int indent));
  43. hidden novalue ret_value     Params((struct token *t, struct node *n,
  44.                                int indent));
  45. hidden novalue ret_1_arg     Params((struct token *t, struct node *args,
  46.                                int typcd, char *vwrd_asgn, char *arg_rep,
  47.                                int indent));
  48. hidden int     rt_walk       Params((struct node *n, int indent, int brace));
  49. hidden novalue spcl_start    Params((struct sym_entry *op_params));
  50. hidden int     tdef_or_extr  Params((struct node *n));
  51. hidden novalue tend_ary      Params((int n));
  52. hidden novalue tend_init     Params((noargs));
  53. hidden novalue tnd_var       Params((struct sym_entry *sym, char *strct_ptr, char *access, int indent));
  54. hidden novalue tok_line      Params((struct token *t, int indent));
  55. hidden novalue typ_asrt      Params((int typcd, struct node *desc,
  56.                                struct token *tok, int indent));
  57. hidden int     typ_case      Params((struct node *var, struct node *slct_lst,
  58.                                struct node *dflt,
  59.                                int (*walk)Params((struct node *n, int indent,
  60.                                  int brace)), int maybe_var, int indent));
  61. hidden novalue untend        Params((int indent));
  62.  
  63. extern char *progname;
  64.  
  65. int op_type = OrdFunc;  /* type of operation */
  66. char lc_letter;         /* f = function, o = operator, k = keyword */
  67. char uc_letter;         /* F = function, O = operator, K = keyword */
  68. char prfx1;             /* 1st char of unique prefix for operation */
  69. char prfx2;             /* 2nd char of unique prefix for operation */
  70. char *fname = "";       /* current source file name */
  71. int line = 0;           /* current source line number */
  72. int nxt_sbuf;           /* next string buffer index */
  73. int nxt_cbuf;           /* next cset buffer index */
  74. int abs_ret = SomeType; /* type from abstract return(s) */
  75.  
  76. int nl = 0;             /* flag indicating the a new-line should be output */
  77. static int no_nl = 0;   /* flag to suppress line directives */
  78.  
  79. static int ntend;       /* number of tended descriptor needed */
  80. static char *tendstrct; /* expression to access struct of tended descriptors */
  81. static char *rslt_loc;  /* expression to access result location */
  82. static int varargs = 0; /* flag: operation takes variable number of arguments */
  83.  
  84. static int no_ret_val;  /* function has return statement with no value */
  85. static struct node *fnc_head; /* header of function being "copied" to output */
  86.  
  87. /*
  88.  * chk_nl - if a new-line is required, output it and indent the next line.
  89.  */
  90. static novalue chk_nl(indent)
  91. int indent;
  92.    {
  93.    int col;
  94.  
  95.    if (nl)  {
  96.       /*
  97.        * new-line required.
  98.        */
  99.       putc('\n', out_file);
  100.       ++line;
  101.       for (col = 0; col < indent; ++col)
  102.          putc(' ', out_file);
  103.       nl = 0;
  104.       }
  105.    }
  106.  
  107. /*
  108.  * line_dir - Output a line directive.
  109.  */
  110. static novalue line_dir(nxt_line, new_fname)
  111. int nxt_line;
  112. char *new_fname;
  113.    {
  114.    char *s;
  115.  
  116.    /*
  117.     * Make sure line directives are desired in the output. Normally,
  118.     *  blank lines surround the directive for readability. However,`
  119.     *  a preceding blank line is suppressed at the beginning of the
  120.     *  output file. In addition, a blank line is suppressed after
  121.     *  the directive if it would force the line number on the directive
  122.     *  to be 0.
  123.     */
  124.    if (line_cntrl) {
  125.       fprintf(out_file, "\n");
  126.       if (line != 0)
  127.          fprintf(out_file, "\n");
  128.       if (nxt_line == 1)
  129.          fprintf(out_file, "#line %d \"", nxt_line);
  130.       else
  131.          fprintf(out_file, "#line %d \"", nxt_line - 1);
  132.       for (s = new_fname; *s != '\0'; ++s) {
  133.          if (*s == '"' || *s == '\\')
  134.             putc('\\', out_file);
  135.          putc(*s, out_file);
  136.          }
  137.       if (nxt_line == 1)
  138.          fprintf(out_file, "\"");
  139.       else
  140.          fprintf(out_file, "\"\n");
  141.       nl = 1;
  142.       --nxt_line;
  143.       }
  144.     else if ((nxt_line > line || fname != new_fname) && line != 0) {
  145.       /*
  146.        * Line directives are disabled, but we are in a situation where
  147.        *  one or two new-lines are desirable.
  148.        */
  149.       if (nxt_line > line + 1 || fname != new_fname)
  150.          fprintf(out_file, "\n");
  151.       nl = 1;
  152.       --nxt_line;
  153.       }
  154.    line = nxt_line;
  155.    fname = new_fname;
  156.    }
  157.  
  158. /*
  159.  * prt_str - print a string to the output file, possibly preceded by
  160.  *   a new-line and indenting.
  161.  */
  162. novalue prt_str(s, indent)
  163. char *s;
  164. int indent;
  165.    {
  166.    chk_nl(indent);
  167.    fprintf(out_file, "%s", s);
  168.    }
  169.  
  170. /*
  171.  * tok_line - determine if a line directive is needed to synchronize the
  172.  *  output file name and line number with an input token.
  173.  */
  174. static novalue tok_line(t, indent)
  175. struct token *t;
  176. int indent;
  177.    {
  178.    int nxt_line;
  179.  
  180.    /*
  181.     * Line directives may be suppressed at certain points during code
  182.     *  output. This is done either by rtt itself using the no_nl flag, or
  183.     *  for macros, by the preprocessor using a flag in the token.
  184.     */
  185.    if (no_nl)
  186.       return;
  187.    if (t->flag & LineChk) {
  188.       /*
  189.        * If blank lines can be used in place of a line directive and no
  190.        *  more than 3 are needed, use them. If the line number and file
  191.        *  name are correct, but we need a new-line, we must output a
  192.        *  line directive so the line number is reset after the "new-line".
  193.        */
  194.       nxt_line = t->line;
  195.       if (fname != t->fname  || line > nxt_line || line + 2 < nxt_line)
  196.          line_dir(nxt_line, t->fname);
  197.       else if (nl && line == nxt_line)
  198.          line_dir(nxt_line, t->fname);
  199.       else if (line != nxt_line) {
  200.          nl = 1;
  201.          --nxt_line;
  202.          while (line < nxt_line) { /* above condition limits # interactions */
  203.             putc('\n', out_file);
  204.             ++line;
  205.             }
  206.          }
  207.       }
  208.    chk_nl(indent);
  209.    }
  210.  
  211. /*
  212.  * prt_tok - print a token.
  213.  */
  214. static novalue prt_tok(t, indent)
  215. struct token *t;
  216. int indent;
  217.    {
  218.    char *s;
  219.  
  220.    tok_line(t, indent); /* synchronize file name and line number */
  221.  
  222.    /*
  223.     * Most tokens contain a string of their exact image. However, string
  224.     *  and character literals lack the surrounding quotes.
  225.     */
  226.    s = t->image;
  227.    switch (t->tok_id) {
  228.       case StrLit:
  229.          fprintf(out_file, "\"%s\"", s);
  230.          break;
  231.       case LStrLit:
  232.          fprintf(out_file, "L\"%s\"", s);
  233.          break;
  234.       case CharConst:
  235.          fprintf(out_file, "'%s'", s);
  236.          break;
  237.       case LCharConst:
  238.          fprintf(out_file, "L'%s'", s);
  239.          break;
  240.       default:
  241.          fprintf(out_file, "%s", s);
  242.       }
  243.    }
  244.  
  245. /*
  246.  * untend - output code to removed the tended descriptors in this
  247.  *  function from the global tended list.
  248.  */
  249. static novalue untend(indent)
  250. int indent;
  251.    {
  252.    ForceNl();
  253.    prt_str("tend = ", indent);
  254.    fprintf(out_file, "%s.previous;", tendstrct);
  255.    ForceNl();
  256.    /*
  257.     * For varargs operations, the tended structure might have been
  258.     *  malloced. If so, it must be freed.
  259.     */
  260.    if (varargs) {
  261.       prt_str("if (r_tendp != (struct tend_desc *)&r_tend)", indent);
  262.       ForceNl();
  263.       prt_str("free((pointer)r_tendp);", 2 * indent);
  264.       }
  265.    }
  266.  
  267. /*
  268.  * tnd_var - output an expression to accessed a tended variable.
  269.  */
  270. static novalue tnd_var(sym, strct_ptr, access, indent)
  271. struct sym_entry *sym;
  272. char *strct_ptr;
  273. char *access;
  274. int indent;
  275.    {
  276.    /*
  277.     * A variable that is a specific block pointer type must be cast
  278.     *  to that pointer type in such a way that it can be used as either
  279.     *  an lvalue or an rvalue:  *(struct b_??? **)&???.vword.bptr
  280.     */
  281.    if (strct_ptr != NULL) {
  282.       prt_str("(*(struct ", indent);
  283.       prt_str(strct_ptr, indent);
  284.       prt_str("**)&", indent);
  285.       }
  286.  
  287.    if (sym->id_type & ByRef) {
  288.       /*
  289.        * The tended variable is being accessed indirectly through
  290.        *  a pointer (that is, it is accessed as the argument to a body
  291.        *  function); dereference its identifier.
  292.        */
  293.       prt_str("(*", indent);
  294.       prt_str(sym->image, indent);
  295.       prt_str(")", indent);
  296.       }
  297.    else {
  298.       if (sym->t_indx >= 0) {
  299.          /*
  300.           * The variable is accessed directly as part of the tended structure.
  301.           */
  302.          prt_str(tendstrct, indent);
  303.          fprintf(out_file, ".d[%d]", sym->t_indx);
  304.          }
  305.       else {
  306.          /*
  307.           * This is a direct access to an operation parameter.
  308.           */
  309.          prt_str("r_args[", indent);
  310.          fprintf(out_file, "%d]", sym->u.param_info.param_num + 1);
  311.          }
  312.       }
  313.    prt_str(access, indent);  /* access the vword for tended pointers */
  314.    if (strct_ptr != NULL)
  315.       prt_str(")", indent);
  316.    }
  317.  
  318. /*
  319.  * prt_var - print a variable.
  320.  */
  321. static novalue prt_var(n, indent)
  322. struct node *n;
  323. int indent;
  324.    {
  325.    struct token *t;
  326.    struct sym_entry *sym;
  327.  
  328.    t = n->tok;
  329.    tok_line(t, indent); /* synchronize file name and line nuber */
  330.    sym = n->u[0].sym;
  331.    switch (sym->id_type & ~ByRef) {
  332.       case TndDesc:
  333.          /*
  334.           * Simple tended descriptor.
  335.           */
  336.          tnd_var(sym, NULL, "", indent);
  337.          break;
  338.       case TndStr:
  339.          /*
  340.           * Tended character pointer.
  341.           */
  342.          tnd_var(sym, NULL, ".vword.sptr", indent);
  343.          break;
  344.       case TndBlk:
  345.          /*
  346.           * Tended block pointer.
  347.           */
  348.          tnd_var(sym, sym->u.tnd_var.blk_name, ".vword.bptr",
  349.             indent);
  350.          break;
  351.       case RtParm:
  352.       case DrfPrm:
  353.          switch (sym->u.param_info.cur_loc) {
  354.             case PrmTend:
  355.                /*
  356.                 * Simple tended parameter.
  357.                 */
  358.                tnd_var(sym, NULL, "", indent);
  359.                break;
  360.             case PrmCStr:
  361.                /*
  362.                 * Parameter converted to a (tended) string.
  363.                 */
  364.                tnd_var(sym, NULL, ".vword.sptr", indent);
  365.                break;
  366.             case PrmInt:
  367.                /*
  368.                 * Parameter converted to a C integer.
  369.                 */
  370.                chk_nl(indent);
  371.                fprintf(out_file, "r_i%d", sym->u.param_info.param_num);
  372.                break;
  373.             case PrmDbl:
  374.                /*
  375.                 * Parameter converted to a C double.
  376.                 */
  377.                chk_nl(indent);
  378.                fprintf(out_file, "r_d%d", sym->u.param_info.param_num);
  379.                break;
  380.             default:
  381.                errt2(t, "Conflicting conversions for: ", t->image);
  382.             }
  383.          break;
  384.       case RtParm | VarPrm:
  385.       case DrfPrm | VarPrm:
  386.          /*
  387.           * Parameter representing variable part of argument list.
  388.           */
  389.          prt_str("(&", indent);
  390.          if (sym->t_indx >= 0)
  391.             fprintf(out_file, "%s.d[%d])", tendstrct, sym->t_indx);
  392.          else
  393.             fprintf(out_file, "r_args[%d])", sym->u.param_info.param_num + 1);
  394.          break;
  395.       case VArgLen:
  396.          /*
  397.           * Length of variable part of argument list.
  398.           */
  399.          prt_str("(r_nargs - ", indent);
  400.          fprintf(out_file, "%d)", params->u.param_info.param_num);
  401.          break;
  402.       case RsltLoc:
  403.          /*
  404.           * "result" the result location of the operation.
  405.           */
  406.          prt_str(rslt_loc, indent);
  407.          break;
  408.       case Label:
  409.          /*
  410.           * Statement label.
  411.           */
  412.          prt_str(sym->image, indent);
  413.          break;
  414.       case OtherDcl:
  415.          /*
  416.           * Some other type of variable: accessed by identifier. If this
  417.           *  is a body function, it may be passed by reference and need
  418.           *  a level of pointer dereferencing.
  419.           */
  420.          if (sym->id_type & ByRef)
  421.             prt_str("(*",indent);
  422.          prt_str(sym->image, indent);
  423.          if (sym->id_type & ByRef)
  424.             prt_str(")",indent);
  425.          break;
  426.       }
  427.    }
  428.  
  429. /*
  430.  * does_call - determine if an expression contains a function call by
  431.  *  walking its syntax tree.
  432.  */
  433. static int does_call(expr)
  434. struct node *expr;
  435.    {
  436.    int n_subs;
  437.    int i;
  438.  
  439.    if (expr == NULL)
  440.       return 0;
  441.    if (expr->nd_id == BinryNd && expr->tok->tok_id == ')')
  442.       return 1;      /* found a function call */
  443.  
  444.    switch (expr->nd_id) {
  445.       case ExactCnv: case PrimryNd: case SymNd:
  446.          n_subs = 0;
  447.          break;
  448.       case CompNd:
  449.          /*
  450.           * Check field 0 below, field 1 is not a subtree, check field 2 here.
  451.           */
  452.          n_subs = 1;
  453.          if (does_call(expr->u[2].child))
  454.              return 1;
  455.          break;
  456.       case IcnTypNd: case PstfxNd: case PreSpcNd: case PrefxNd:
  457.          n_subs = 1;
  458.          break;
  459.       case AbstrNd: case BinryNd: case CommaNd: case ConCatNd: case LstNd:
  460.       case StrDclNd:
  461.          n_subs = 2;
  462.          break;
  463.       case TrnryNd:
  464.          n_subs = 3;
  465.          break;
  466.       case QuadNd:
  467.          n_subs = 4;
  468.          break;
  469.       default:
  470.          fprintf(stdout, "rtt internal error: unknown node type\n");
  471.          exit(ErrorExit);
  472.          }
  473.  
  474.    for (i = 0; i < n_subs; ++i)
  475.       if (does_call(expr->u[i].child))
  476.           return 1;
  477.  
  478.    return 0;
  479.    }
  480.  
  481. /*
  482.  * prt_runerr - print code to implement runerr().
  483.  */
  484. static novalue prt_runerr(t, num, val, indent)
  485. struct token *t;
  486. struct node *num;
  487. struct node *val;
  488. int indent;
  489.    {
  490.    if (op_type == OrdFunc)
  491.       errt1(t, "'runerr' may not be used in an ordinary C function");
  492.  
  493.    tok_line(t, indent);  /* synchronize file name and line number */
  494.    prt_str("{", indent);
  495.    ForceNl();
  496.    prt_str("err_msg(", indent);
  497.    c_walk(num, indent, 0);                /* error number */
  498.    if (val == NULL)
  499.       prt_str(", NULL);", indent);        /* no offending value */
  500.    else {
  501.       prt_str(", &(", indent);
  502.       c_walk(val, indent, 0);             /* offending value */
  503.       prt_str("));", indent);
  504.       }
  505.    /*
  506.     * Handle error conversion. Indicate that operation may fail because
  507.     *  of error conversion and produce the necessary code.
  508.     */
  509.    cur_impl->ret_flag |= DoesEFail;
  510.    failure(indent, 1);
  511.    prt_str("}", indent);
  512.    ForceNl();
  513.    }
  514.  
  515. /*
  516.  * typ_name - convert a type code to a string that can be used to
  517.  *  output "T_" or "D_" type codes.
  518.  */
  519. char *typ_name(typcd, tok)
  520. int typcd;
  521. struct token *tok;
  522.    {
  523.    if (typcd == Empty_type)
  524.       errt1(tok, "it is meaningless to assert a type of empty_type");
  525.    else if (typcd == Any_value)
  526.       errt1(tok, "it is useless to assert a type of any_value");
  527.    else if (typcd < 0 || typcd == str_typ)
  528.       return NULL;
  529.    else
  530.       return icontypes[typcd].cap_id;
  531.    }
  532.  
  533. /*
  534.  * Produce a C conditional expression to check a descriptor for a
  535.  *  particular type.
  536.  */
  537. static novalue typ_asrt(typcd, desc, tok, indent)
  538. int typcd;
  539. struct node *desc;
  540. struct token *tok;
  541. int indent;
  542.    {
  543.    tok_line(tok, indent);
  544.  
  545.    if (typcd == str_typ) {
  546.       /*
  547.        * Check dword for the absense of a "not qualifier" flag.
  548.        */
  549.       prt_str("(!((", indent);
  550.       c_walk(desc, indent, 0);
  551.       prt_str(").dword & F_Nqual))", indent);
  552.       }
  553.    else if (typcd == TypVar) {
  554.       /*
  555.        * Check dword for the presense of a "variable" flag.
  556.        */
  557.       prt_str("(((", indent);
  558.       c_walk(desc, indent, 0);
  559.       prt_str(").dword & D_Var) == D_Var)", indent);
  560.       }
  561.    else if (typcd == int_typ) {
  562.       /*
  563.        * If large integers are supported, an integer can be either
  564.        *  an ordinary integer or a large integer.
  565.        */
  566.       ForceNl();
  567.       prt_str("#ifdef LargeInts", 0);
  568.       ForceNl();
  569.       prt_str("(((", indent);
  570.       c_walk(desc, indent, 0);
  571.       prt_str(").dword == D_Integer) || ((", indent);
  572.       c_walk(desc, indent, 0);
  573.       prt_str(").dword == D_Lrgint))", indent);
  574.       ForceNl();
  575.       prt_str("#else\t\t\t\t\t/* LargeInts */", 0);
  576.       ForceNl();
  577.       prt_str("((", indent);
  578.       c_walk(desc, indent, 0);
  579.       prt_str(").dword == D_Integer)", indent);
  580.       ForceNl();
  581.       prt_str("#endif\t\t\t\t\t/* LargeInts */", 0);
  582.       ForceNl();
  583.       }
  584.    else {
  585.       /*
  586.        * Check dword for a specific type code.
  587.        */
  588.       prt_str("((", indent);
  589.       c_walk(desc, indent, 0);
  590.       prt_str(").dword == D_", indent);
  591.       prt_str(typ_name(typcd, tok), indent);
  592.       prt_str(")", indent);
  593.       }
  594.    }
  595.  
  596. /*
  597.  * retval_dcltor - convert the "declarator" part of function declaration
  598.  *  into a declarator for the variable "r_retval" of the same type
  599.  *  as the function result type, outputing the new declarator. This
  600.  *  variable is a temporary location to store the result of the argument
  601.  *  to a C return statement.
  602.  */
  603. static int retval_dcltor(dcltor, indent)
  604. struct node *dcltor;
  605. int indent;
  606.    {
  607.    int flag;
  608.  
  609.    switch (dcltor->nd_id) {
  610.       case ConCatNd:
  611.          c_walk(dcltor->u[0].child, indent, 0);
  612.          retval_dcltor(dcltor->u[1].child, indent);
  613.          return NotId;
  614.       case PrimryNd:
  615.          /*
  616.           * We have reached the function name. Replace it with "r_retval"
  617.           *  and tell caller we have found it.
  618.           */
  619.          prt_str("r_retval", indent);
  620.          return IsId;
  621.       case PrefxNd:
  622.          /*
  623.           * (...)
  624.           */
  625.          prt_str("(", indent);
  626.          flag = retval_dcltor(dcltor->u[0].child, indent);
  627.          prt_str(")", indent);
  628.          return flag;
  629.       case BinryNd:
  630.          if (dcltor->tok->tok_id == ')') {
  631.             /*
  632.              * Function declaration. If this is the declarator that actually
  633.              *  defines the function being processed, discard the paramater
  634.              *  list including parentheses.
  635.              */
  636.             if (retval_dcltor(dcltor->u[0].child, indent) == NotId) {
  637.                prt_str("(", indent);
  638.                c_walk(dcltor->u[1].child, indent, 0);
  639.                prt_str(")", indent);
  640.                }
  641.             }
  642.          else {
  643.             /*
  644.              * Array.
  645.              */
  646.             retval_dcltor(dcltor->u[0].child, indent);
  647.             prt_str("[", indent);
  648.             c_walk(dcltor->u[1].child, indent, 0);
  649.             prt_str("]", indent);
  650.             }
  651.          return NotId;
  652.       }
  653.    err1("rtt internal error detected in function retval_dcltor()");
  654.    /* NOTREACHED */
  655.    }
  656.  
  657. /*
  658.  * cnv_fnc - produce code to handle RTT cnv: and def: constructs.
  659.  */
  660. static novalue cnv_fnc(t, typcd, src, dflt, dest, indent)
  661. struct token *t;
  662. int typcd;
  663. struct node *src;
  664. struct node *dflt;
  665. struct node *dest;
  666. int indent;
  667.    {
  668.    int dflt_to_ptr;
  669.    int loc;
  670.    int is_cstr;
  671.  
  672.    if (src->nd_id == SymNd && src->u[0].sym->id_type & VarPrm)
  673.       errt1(t, "converting entire variable part of param list not supported");
  674.  
  675.    tok_line(t, indent); /* synchronize file name and line number */
  676.  
  677.    /*
  678.     * Initial assumptions: result of conversion is a tended location
  679.     *   and is not tended C string.
  680.     */
  681.    loc = PrmTend;
  682.    is_cstr = 0;
  683.  
  684.   /*
  685.    * Print the name of the conversion function. If it is a conversion
  686.    *  with a default value, determine (through dflt_to_prt) if the
  687.    *  default value is passed by-reference instead of by-value.
  688.    */
  689.    prt_str(cnv_name(typcd, dflt, &dflt_to_ptr), indent);
  690.    prt_str("(", indent);
  691.  
  692.    /*
  693.     * Determine what parameter scope, if any, is established by this
  694.     *  conversion. If the conversion needs a buffer, allocate it and
  695.     *  put it in the argument list.
  696.     */
  697.    switch (typcd) {
  698.       case TypCInt:
  699.       case TypECInt:
  700.          loc = PrmInt;
  701.          break;
  702.       case TypCDbl:
  703.          loc = PrmDbl;
  704.          break;
  705.       case TypCStr:
  706.          is_cstr = 1;
  707.          break;
  708.       case TypTStr:
  709.          fprintf(out_file, "r_sbuf[%d], ", nxt_sbuf++);
  710.          break;
  711.       case TypTCset:
  712.          fprintf(out_file, "&r_cbuf[%d], ", nxt_cbuf++);
  713.          break;
  714.       }
  715.  
  716.    /*
  717.     * Output source of conversion.
  718.     */
  719.    prt_str("&(", indent);
  720.    c_walk(src, indent, 0);
  721.    prt_str("), ", indent);
  722.  
  723.    /*
  724.     * If there is a default value, output it, taking its address if necessary.
  725.     */
  726.    if (dflt != NULL) {
  727.       if (dflt_to_ptr)
  728.          prt_str("&(", indent);
  729.       c_walk(dflt, indent, 0);
  730.       if (dflt_to_ptr)
  731.          prt_str("), ", indent);
  732.       else
  733.          prt_str(", ", indent);
  734.       }
  735.  
  736.    /*
  737.     * Output the destination of the conversion. This may or may not be
  738.     *  the same as the source.
  739.     */
  740.    prt_str("&(", indent);
  741.    if (dest == NULL) {
  742.       /*
  743.        * Convert "in place", changing the location of a paramater if needed.
  744.        */
  745.       if (src->nd_id == SymNd && src->u[0].sym->id_type & (RtParm | DrfPrm)) {
  746.          if (src->u[0].sym->id_type & DrfPrm)
  747.             src->u[0].sym->u.param_info.cur_loc = loc;
  748.          else
  749.             errt1(t, "only dereferenced parameter can be converted in-place");
  750.          }
  751.       else if ((loc != PrmTend) | is_cstr)
  752.          errt1(t,
  753.             "only ordinary parameters can be converted in-place to C values");
  754.       c_walk(src, indent, 0);
  755.       if (is_cstr) {
  756.          /*
  757.           * The parameter must be accessed as a tended C string, but only
  758.           *  now, after the "destination" code has been produced as a full
  759.           *  descriptor.
  760.           */
  761.          src->u[0].sym->u.param_info.cur_loc = PrmCStr;
  762.          }
  763.       }
  764.    else {
  765.       /*
  766.        * Convert to an explicit destination.
  767.        */
  768.       if (is_cstr) {
  769.          /*
  770.           * Access the destination as a full descriptor even though it
  771.           *  must be declared as a tended C string.
  772.           */
  773.          if (dest->nd_id != SymNd || (dest->u[0].sym->id_type != TndStr &&
  774.                dest->u[0].sym->id_type != TndDesc))
  775.             errt1(t,
  776.              "dest. of C_string conv. must be tended descriptor or char *");
  777.          tnd_var(dest->u[0].sym, NULL, "", indent);
  778.          }
  779.       else
  780.          c_walk(dest, indent, 0);
  781.       }
  782.    prt_str("))", indent);
  783.    }
  784.  
  785. /*
  786.  * cnv_name - produce name of conversion routine. Warning, name is
  787.  *   constructed in a static buffer. Also determine if a default
  788.  *   must be passed "by reference".
  789.  */
  790. char *cnv_name(typcd, dflt, dflt_to_ptr)
  791. int typcd;
  792. struct node *dflt;
  793. int *dflt_to_ptr;
  794.    {
  795.    static char buf[15];
  796.    int by_ref;
  797.  
  798.    /*
  799.     * The names of simple conversion and defaulting conversions have
  800.     *  the same suffixes, but different prefixes.
  801.     */
  802.    if (dflt == NULL)
  803.       strcpy(buf , "cnv_");
  804.    else
  805.        strcpy(buf, "def_");
  806.  
  807.    by_ref = 0;
  808.    switch (typcd) {
  809.       case TypCInt:
  810.          strcat(buf, "c_int");
  811.          break;
  812.       case TypCDbl:
  813.          strcat(buf, "c_dbl");
  814.          break;
  815.       case TypCStr:
  816.          strcat(buf, "c_str");
  817.          break;
  818.       case TypTStr:
  819.          strcat(buf, "tstr");
  820.          by_ref = 1;
  821.          break;
  822.       case TypTCset:
  823.          strcat(buf, "tcset");
  824.          by_ref = 1;
  825.          break;
  826.       case TypEInt:
  827.          strcat(buf, "eint");
  828.          break;
  829.       case TypECInt:
  830.          strcat(buf, "ec_int");
  831.          break;
  832.       default:
  833.          if (typcd == cset_typ) {
  834.             strcat(buf, "cset");
  835.             by_ref = 1;
  836.             }
  837.          else if (typcd == int_typ)
  838.             strcat(buf, "int");
  839.          else if (typcd == real_typ)
  840.             strcat(buf, "real");
  841.          else if (typcd == str_typ) {
  842.             strcat(buf, "str");
  843.             by_ref = 1;
  844.             }
  845.       }
  846.    if (dflt_to_ptr != NULL)
  847.       *dflt_to_ptr = by_ref;
  848.    return buf;
  849.    }
  850.  
  851. /*
  852.  * ret_value - produce code to set the result location of an operation
  853.  *  using the expression on a return or suspend.
  854.  */
  855. static novalue ret_value(t, n, indent)
  856. struct token *t;
  857. struct node *n;
  858. int indent;
  859.    {
  860.    struct node *caller;
  861.    struct node *args;
  862.    int typcd;
  863.  
  864.    if (n == NULL)
  865.       errt1(t, "there is no default return value for run-time operations");
  866.  
  867.    if (n->nd_id == SymNd && n->u[0].sym->id_type == RsltLoc) {
  868.       /*
  869.        * return/suspend result;
  870.        *
  871.        *   result already where it needs to be.
  872.        */
  873.       return;
  874.       }
  875.  
  876.    if (n->nd_id == PrefxNd && n->tok != NULL) {
  877.       switch (n->tok->tok_id) {
  878.          case C_Integer:
  879.             /*
  880.              * return/suspend C_integer <expr>;
  881.              */
  882.             prt_str(rslt_loc, indent);
  883.             prt_str(".vword.integr = ", indent);
  884.             c_walk(n->u[0].child, indent + IndentInc, 0);
  885.             prt_str(";", indent);
  886.             ForceNl();
  887.             prt_str(rslt_loc, indent);
  888.             prt_str(".dword = D_Integer;", indent);
  889.             chkabsret(t, int_typ);  /* compare return with abstract return */
  890.             return;
  891.          case C_Double:
  892.             /*
  893.              * return/suspend C_double <expr>;
  894.              */
  895.             prt_str(rslt_loc, indent);
  896.             prt_str(".vword.bptr = (union block *)alcreal(", indent);
  897.             c_walk(n->u[0].child, indent + IndentInc, 0);
  898.             prt_str(");", indent + IndentInc);
  899.             ForceNl();
  900.             prt_str(rslt_loc, indent);
  901.             prt_str(".dword = D_Real;", indent);
  902.             /*
  903.              * The allocation of the real block may fail.
  904.              */
  905.             chk_rsltblk(indent);
  906.             chkabsret(t, real_typ); /* compare return with abstract return */
  907.             return;
  908.          case C_String:
  909.             /*
  910.              * return/suspend C_string <expr>;
  911.              */
  912.             prt_str(rslt_loc, indent);
  913.             prt_str(".vword.sptr = ", indent);
  914.             c_walk(n->u[0].child, indent + IndentInc, 0);
  915.             prt_str(";", indent);
  916.             ForceNl();
  917.             prt_str(rslt_loc, indent);
  918.             prt_str(".dword = strlen(", indent);
  919.             prt_str(rslt_loc, indent);
  920.             prt_str(".vword.sptr);", indent);
  921.             chkabsret(t, str_typ); /* compare return with abstract return */
  922.             return;
  923.          }
  924.       }
  925.    else if (n->nd_id == BinryNd && n->tok->tok_id == ')') {
  926.       /*
  927.        * Return value is in form of function call, see if it is really
  928.        *  a descriptor constructor.
  929.        */
  930.       caller = n->u[0].child;
  931.       args = n->u[1].child;
  932.       if (caller->nd_id == SymNd) {
  933.          switch (caller->tok->tok_id) {
  934.             case IconType:
  935.                typcd = caller->u[0].sym->u.typ_indx;
  936.                switch (icontypes[typcd].rtl_ret) {
  937.                   case TRetBlkP:
  938.                      /*
  939.                       * return/suspend <type>(<block-pntr>);
  940.                       */
  941.                      ret_1_arg(t, args, typcd, ".vword.bptr = (union block *)",
  942.                         "(bp)", indent);
  943.                      break;
  944.                   case TRetDescP:
  945.                      /*
  946.                       * return/suspend <type>(<desc-pntr>);
  947.                       */
  948.                      ret_1_arg(t, args, typcd, ".vword.descptr = (dptr)",
  949.                         "(dp)", indent);
  950.                      break;
  951.                   case TRetCharP:
  952.                      /*
  953.                       * return/suspend <type>(<char-pntr>);
  954.                       */
  955.                      ret_1_arg(t, args, typcd, ".vword.sptr = (char *)",
  956.                         "(s)", indent);
  957.                      break;
  958.                   case TRetCInt:
  959.                      /*
  960.                       * return/suspend <type>(<integer>);
  961.                       */
  962.                      ret_1_arg(t, args, typcd, ".vword.integr = (word)",
  963.                         "(i)", indent);
  964.                      break;
  965.                   case TRetSpcl:
  966.                      if (typcd == str_typ) {
  967.                         /*
  968.                          * return/suspend string(<len>, <char-pntr>);
  969.                          */
  970.                         if (args == NULL || args->nd_id != CommaNd ||
  971.                            args->u[0].child->nd_id == CommaNd)
  972.                            errt1(t, "wrong no. of args for string(n, s)");
  973.                         prt_str(rslt_loc, indent);
  974.                         prt_str(".vword.sptr = ", indent);
  975.                         c_walk(args->u[1].child, indent + IndentInc, 0);
  976.                         prt_str(";", indent);
  977.                         ForceNl();
  978.                         prt_str(rslt_loc, indent);
  979.                         prt_str(".dword = ", indent);
  980.                         c_walk(args->u[0].child, indent + IndentInc, 0);
  981.                         prt_str(";", indent);
  982.                         }
  983.                      else if (typcd == stv_typ) {
  984.                         /*
  985.                          * return/suspend tvsubs(<desc-pntr>, <start>, <len>);
  986.                          */
  987.                         if (args == NULL || args->nd_id != CommaNd ||
  988.                            args->u[0].child->nd_id != CommaNd ||
  989.                            args->u[0].child->u[0].child->nd_id == CommaNd)
  990.                            errt1(t, "wrong no. of args for tvsubs(dp, i, j)");
  991.                         no_nl = 1;
  992.                         prt_str("SubStr(&", indent);
  993.                         prt_str(rslt_loc, indent);
  994.                         prt_str(", ", indent);
  995.                         c_walk(args->u[0].child->u[0].child, indent + IndentInc,
  996.                            0);
  997.                         prt_str(", ", indent + IndentInc);
  998.                         c_walk(args->u[1].child, indent + IndentInc, 0);
  999.                         prt_str(", ", indent + IndentInc);
  1000.                         c_walk(args->u[0].child->u[1].child, indent + IndentInc,
  1001.                           0);
  1002.                         prt_str(");", indent + IndentInc);
  1003.                         no_nl = 0;
  1004.                         /*
  1005.                          * The allocation of the substring trapped variable
  1006.                          *   block may fail.
  1007.                          */
  1008.                         chk_rsltblk(indent);
  1009.                         chkabsret(t, stv_typ); /* compare to abstract return */
  1010.                         }
  1011.                      break;
  1012.                   }
  1013.                chkabsret(t, typcd); /* compare return with abstract return */
  1014.                return;
  1015.             case Named_var:
  1016.                /*
  1017.                 * return/suspend named_var(<desc-pntr>);
  1018.                 */
  1019.                if (args == NULL || args->nd_id == CommaNd)
  1020.                   errt1(t, "wrong no. of args for named_var(dp)");
  1021.                prt_str(rslt_loc, indent);
  1022.                prt_str(".vword.descptr = ", indent);
  1023.                c_walk(args, indent + IndentInc, 0);
  1024.                prt_str(";", indent);
  1025.                ForceNl();
  1026.                prt_str(rslt_loc, indent);
  1027.                prt_str(".dword = D_Var;", indent);
  1028.                chkabsret(t, TypVar); /* compare return with abstract return */
  1029.                return;
  1030.             case Struct_var:
  1031.                /*
  1032.                 * return/suspend struct_var(<desc-pntr>, <block_pntr>);
  1033.                 */
  1034.                if (args == NULL || args->nd_id != CommaNd ||
  1035.                   args->u[0].child->nd_id == CommaNd)
  1036.                   errt1(t, "wrong no. of args for struct_var(dp, bp)");
  1037.                prt_str(rslt_loc, indent);
  1038.                prt_str(".vword.descptr = (dptr)", indent);
  1039.                c_walk(args->u[1].child, indent + IndentInc, 0);
  1040.                prt_str(";", indent);
  1041.                ForceNl();
  1042.                prt_str(rslt_loc, indent);
  1043.                prt_str(".dword = D_Var + ((word *)", indent);
  1044.                c_walk(args->u[0].child, indent + IndentInc, 0);
  1045.                prt_str(" - (word *)", indent+IndentInc);
  1046.                prt_str(rslt_loc, indent);
  1047.                prt_str(".vword.descptr);", indent+IndentInc);
  1048.                ForceNl();
  1049.                chkabsret(t, TypVar); /* compare return with abstract return */
  1050.                return;
  1051.             }
  1052.          }
  1053.       }
  1054.  
  1055.    /*
  1056.     * If it is not one of the special returns, it is just a return of
  1057.     *  a descriptor.
  1058.     */
  1059.    prt_str(rslt_loc, indent);
  1060.    prt_str(" = ", indent);
  1061.    c_walk(n, indent + IndentInc, 0);
  1062.    prt_str(";", indent);
  1063.    chkabsret(t, SomeType); /* check for preceding abstract return */
  1064.    }
  1065.  
  1066. /*
  1067.  * ret_1_arg - produce code for a special return/suspend with one argument.
  1068.  */
  1069. static novalue ret_1_arg(t, args, typcd, vwrd_asgn, arg_rep, indent)
  1070. struct token *t;
  1071. struct node *args;
  1072. int typcd;
  1073. char *vwrd_asgn;
  1074. char *arg_rep;
  1075. int indent;
  1076.    {
  1077.    if (args == NULL || args->nd_id == CommaNd)
  1078.       errt3(t, "wrong no. of args for", icontypes[typcd].id, arg_rep);
  1079.  
  1080.    /*
  1081.     * Assignment to vword of result descriptor.
  1082.     */
  1083.    prt_str(rslt_loc, indent);
  1084.    prt_str(vwrd_asgn, indent);
  1085.    c_walk(args, indent + IndentInc, 0);
  1086.    prt_str(";", indent);
  1087.    ForceNl();
  1088.  
  1089.    /*
  1090.     * Assignment to dword of result descriptor.
  1091.     */
  1092.    prt_str(rslt_loc, indent);
  1093.    prt_str(".dword = D_", indent);
  1094.    prt_str(icontypes[typcd].cap_id, indent);
  1095.    prt_str(";", indent);
  1096.    }
  1097.  
  1098. /*
  1099.  * chk_rsltblk - the result value contains an allocated block, make sure
  1100.  *    the allocation succeeded.
  1101.  */
  1102. static novalue chk_rsltblk(indent)
  1103. int indent;
  1104.    {
  1105.    ForceNl();
  1106.    prt_str("if (", indent);
  1107.    prt_str(rslt_loc, indent);
  1108.    prt_str(".vword.bptr == NULL) {", indent);
  1109.    ForceNl();
  1110.    prt_str("err_msg(307, NULL);", indent + IndentInc);
  1111.    ForceNl();
  1112.    /*
  1113.     * Handle error conversion. Indicate that operation may fail because
  1114.     *  of error conversion and produce the necessary code.
  1115.     */
  1116.    cur_impl->ret_flag |= DoesEFail;
  1117.    failure(indent + IndentInc, 1);
  1118.    prt_str("}", indent + IndentInc);
  1119.    ForceNl();
  1120.    }
  1121.  
  1122. /*
  1123.  * failure - produce code for fail or efail.
  1124.  */
  1125. static novalue failure(indent, brace)
  1126. int indent;
  1127. int brace;
  1128.    {
  1129.    /*
  1130.     * If there are tended variables, they must be removed from the tended
  1131.     *  list. The C function may or may not return an explicit signal.
  1132.     */
  1133.    ForceNl();
  1134.    if (ntend != 0) {
  1135.       if (!brace)
  1136.          prt_str("{", indent);
  1137.       untend(indent);
  1138.       ForceNl();
  1139.       if (fnc_ret == RetSig)
  1140.          prt_str("return A_Resume;", indent);
  1141.       else
  1142.          prt_str("return;", indent);
  1143.       if (!brace) {
  1144.          ForceNl();
  1145.          prt_str("}", indent);
  1146.          }
  1147.       }
  1148.    else
  1149.       if (fnc_ret == RetSig)
  1150.          prt_str("return A_Resume;", indent);
  1151.       else
  1152.          prt_str("return;", indent);
  1153.    ForceNl();
  1154.    }
  1155.  
  1156. /*
  1157.  * c_walk - walk the syntax tree for extended C code and output the
  1158.  *  corresponding ordinary C. Return and indication of whether execution
  1159.  *  falls through the code.
  1160.  */
  1161. int c_walk(n, indent, brace)
  1162. struct node *n;
  1163. int indent;
  1164. int brace;
  1165.    {
  1166.    struct token *t;
  1167.    struct node *n1;
  1168.    struct sym_entry *sym;
  1169.    int fall_thru;
  1170.    int save_break;
  1171.    static int does_break = 0;
  1172.    static int may_brnchto;  /* may reach end of code by branching into middle */
  1173.  
  1174.    if (n == NULL)
  1175.       return 1;
  1176.  
  1177.    t =  n->tok;
  1178.  
  1179.    switch (n->nd_id) {
  1180.       case PrimryNd:
  1181.          switch (t->tok_id) {
  1182.             case Fail:
  1183.                if (op_type == OrdFunc)
  1184.                   errt1(t, "'fail' may not be used in an ordinary C function");
  1185.                cur_impl->ret_flag |= DoesFail;
  1186.                failure(indent, brace);
  1187.            chkabsret(t, SomeType);  /* check preceding abstract return */
  1188.            return 0;
  1189.         case Errorfail:
  1190.            if (op_type == OrdFunc)
  1191.           errt1(t,
  1192.               "'errorfail' may not be used in an ordinary C function");
  1193.            cur_impl->ret_flag |= DoesEFail;
  1194.            failure(indent, brace);
  1195.            return 0;
  1196.             case Break:
  1197.            prt_tok(t, indent);
  1198.            prt_str(";", indent);
  1199.                does_break = 1;
  1200.                return 0;
  1201.         default:
  1202.                /*
  1203.                 * Other "primary" expressions are just their token image,
  1204.                 *  possibly followed by a semicolon.
  1205.                 */
  1206.            prt_tok(t, indent);
  1207.            if (t->tok_id == Continue)
  1208.           prt_str(";", indent);
  1209.                return 1;
  1210.         }
  1211.       case PrefxNd:
  1212.      switch (t->tok_id) {
  1213.         case Sizeof:
  1214.            prt_tok(t, indent);                /* sizeof */
  1215.            prt_str("(", indent);
  1216.            c_walk(n->u[0].child, indent, 0);
  1217.            prt_str(")", indent);
  1218.            return 1;
  1219.         case '{':
  1220.                /*
  1221.                 * Initializer list.
  1222.                 */
  1223.            prt_tok(t, indent + IndentInc);     /* { */
  1224.            c_walk(n->u[0].child, indent + IndentInc, 0);
  1225.            prt_str("}", indent + IndentInc);
  1226.            return 1;
  1227.         case Default:
  1228.            prt_tok(t, indent - IndentInc);     /* default (un-indented) */
  1229.            prt_str(": ", indent - IndentInc);
  1230.            fall_thru = c_walk(n->u[0].child, indent, 0);
  1231.                may_brnchto = 1;
  1232.                return fall_thru;
  1233.         case Goto:
  1234.            prt_tok(t, indent);                 /* goto */
  1235.            prt_str(" ", indent);
  1236.            c_walk(n->u[0].child, indent, 0);
  1237.            prt_str(";", indent);
  1238.            return 0;
  1239.         case Return:
  1240.            if (n->u[0].child != NULL)
  1241.           no_ret_val = 0;  /* note that return statement has no value */
  1242.  
  1243.            if (op_type == OrdFunc || fnc_ret == RetInt ||
  1244.           fnc_ret == RetDbl) {
  1245.           /*
  1246.            * ordinary C return: ignore C_integer, C_double, and
  1247.            *  C_string qualifiers on return expression (the first
  1248.            *  two may legally occur when fnc_ret is RetInt or RetDbl).
  1249.            */
  1250.           n1 = n->u[0].child;
  1251.           if (n1 != NULL && n1->nd_id == PrefxNd && n1->tok != NULL) {
  1252.              switch (n1->tok->tok_id) {
  1253.             case C_Integer:
  1254.             case C_Double:
  1255.             case C_String:
  1256.                n1 = n1->u[0].child;
  1257.             }
  1258.              }
  1259.           if (ntend != 0) {
  1260.                      /*
  1261.                       * There are tended variables that must be removed from
  1262.                       *  the tended list.
  1263.                       */
  1264.              if (!brace)
  1265.             prt_str("{", indent);
  1266.              if (does_call(n1)) {
  1267.             /*
  1268.              * The return expression contains a function call;
  1269.                          *  the variables must remain tended while it is
  1270.                          *  computed, so compute it into a temporary variable
  1271.                          *  named r_retval.Output a declaration for r_retval;
  1272.                          *  its type must match the return type of the C
  1273.                          *  function.
  1274.                          */
  1275.             ForceNl();
  1276.             prt_str("register ", indent);
  1277.             if (op_type == OrdFunc) {
  1278.                no_nl = 1;
  1279.                just_type(fnc_head->u[0].child, indent, 0);
  1280.                prt_str(" ", indent);
  1281.                retval_dcltor(fnc_head->u[1].child, indent);
  1282.                prt_str(";", indent);
  1283.                no_nl = 0;
  1284.                }
  1285.             else if (fnc_ret == RetInt)
  1286.                prt_str("C_integer r_retval;", indent);
  1287.             else    /* fnc_ret == RetDbl */
  1288.                prt_str("double r_retval;", indent);
  1289.             ForceNl();
  1290.  
  1291.                         /*
  1292.                          * Output code to compute the return value, untend
  1293.                          *  the variable, then return the value.
  1294.                          */
  1295.             prt_str("r_retval = ", indent);
  1296.             c_walk(n1, indent + IndentInc, 0);
  1297.             prt_str(";", indent);
  1298.             untend(indent);
  1299.             ForceNl();
  1300.             prt_str("return r_retval;", indent);
  1301.             }
  1302.              else {
  1303.                         /*
  1304.                          * It is safe to untend the variables and return
  1305.                          *  the result value directly with a return
  1306.                          *  statement.
  1307.                          */
  1308.             untend(indent);
  1309.             ForceNl();
  1310.             prt_tok(t, indent);    /* return */
  1311.             prt_str(" ", indent);
  1312.             c_walk(n1, indent, 0);
  1313.             prt_str(";", indent);
  1314.             }
  1315.              if (!brace) {
  1316.             ForceNl();
  1317.             prt_str("}", indent);
  1318.             }
  1319.              ForceNl();
  1320.              }
  1321.           else {
  1322.                      /*
  1323.                       * There are no tended variable, just output the
  1324.                       *  return expression.
  1325.                       */
  1326.              prt_tok(t, indent);     /* return */
  1327.              prt_str(" ", indent);
  1328.              c_walk(n1, indent, 0);
  1329.              prt_str(";", indent);
  1330.              }
  1331.  
  1332.                   /*
  1333.                    * If this is a body function, check the return against
  1334.                    *  preceding abstract returns.
  1335.                    */
  1336.           if (fnc_ret == RetInt)
  1337.              chkabsret(n->tok, int_typ);
  1338.                   else if (fnc_ret == RetDbl)
  1339.                      chkabsret(n->tok, real_typ);
  1340.                   }
  1341.                else {
  1342.                   /*
  1343.                    * Return from Icon operation. Indicate that the operation
  1344.                    *  returns, compute the value into the result location,
  1345.                    *  untend variables if necessary, and return a signal
  1346.                    *  if the function requires one.
  1347.                    */
  1348.                   cur_impl->ret_flag |= DoesRet;
  1349.                   ForceNl();
  1350.                   if (!brace) {
  1351.                      prt_str("{", indent);
  1352.                      ForceNl();
  1353.                      }
  1354.                   ret_value(t, n->u[0].child, indent);
  1355.                   if (ntend != 0)
  1356.                      untend(indent);
  1357.                   ForceNl();
  1358.                   if (fnc_ret == RetSig)
  1359.                      prt_str("return A_Continue;", indent);
  1360.                   else if (fnc_ret == RetNoVal)
  1361.                      prt_str("return;", indent);
  1362.                   ForceNl();
  1363.                   if (!brace) {
  1364.                      prt_str("}", indent);
  1365.                      ForceNl();
  1366.                      }
  1367.                   }
  1368.                return 0;
  1369.             case Suspend:
  1370.                if (op_type == OrdFunc)
  1371.                   errt1(t, "'suspend' may not be used in an ordinary C function"
  1372.                      );
  1373.                cur_impl->ret_flag |= DoesSusp; /* note suspension */
  1374.                ForceNl();
  1375.                if (!brace) {
  1376.                   prt_str("{", indent);
  1377.                   ForceNl();
  1378.                   }
  1379.                prt_str("register int signal;", indent + IndentInc);
  1380.                ForceNl();
  1381.                ret_value(t, n->u[0].child, indent);
  1382.                ForceNl();
  1383.                /*
  1384.                 * The operator suspends by calling the success continuation
  1385.                 *  if there is one or just returns if there is none. For
  1386.                 *  the interpreter, interp() is the success continuation.
  1387.                 *  A non-A_Resume signal from the success continuation must
  1388.                 *  returned to the caller. If there are tended variables
  1389.                 *  they must be removed from the tended list before a signal
  1390.                 *  is returned.
  1391.                 */
  1392.                if (iconx_flg) {
  1393. #ifdef EventMon
  1394.           switch (op_type) {
  1395.           case Function:
  1396.              prt_str(
  1397.                "if ((signal = interp(G_Fsusp, r_args)) != A_Resume) {",
  1398.                  indent);
  1399.              break;
  1400.           case Operator:
  1401.           case Keyword:
  1402.              prt_str(
  1403.                "if ((signal = interp(G_Osusp, r_args)) != A_Resume) {",
  1404.                  indent);
  1405.              break;
  1406.           default:
  1407.              prt_str(
  1408.                "if ((signal = interp(G_Csusp, r_args)) != A_Resume) {",
  1409.                  indent);
  1410.           }
  1411. #else                    /* EventMon */
  1412.           prt_str(
  1413.             "if ((signal = interp(G_Csusp, r_args)) != A_Resume) {",
  1414.               indent);
  1415. #endif                    /* EventMon */
  1416.           }
  1417.                else {
  1418.                   prt_str("if (r_s_cont == (continuation)NULL) {", indent);
  1419.                   if (ntend != 0)
  1420.                      untend(indent + IndentInc);
  1421.                   ForceNl();
  1422.                   prt_str("return A_Continue;", indent + IndentInc);
  1423.                   ForceNl();
  1424.                   prt_str("}", indent + IndentInc);
  1425.                   ForceNl();
  1426.                   prt_str("else if ((signal = (*r_s_cont)()) != A_Resume) {",
  1427.                      indent);
  1428.                   }
  1429.                ForceNl();
  1430.                if (ntend != 0)
  1431.                   untend(indent + IndentInc);
  1432.                ForceNl();
  1433.                prt_str("return signal;", indent + IndentInc);
  1434.                ForceNl();
  1435.                prt_str("}", indent + IndentInc);
  1436.                if (!brace) {
  1437.                   prt_str("}", indent);
  1438.                   ForceNl();
  1439.                   }
  1440.                return 1;
  1441.             case '(':
  1442.                /*
  1443.                 * Parenthesized expression.
  1444.                 */
  1445.                prt_tok(t, indent);     /* ( */
  1446.                fall_thru = c_walk(n->u[0].child, indent, 0);
  1447.                prt_str(")", indent);
  1448.                return fall_thru;
  1449.             default:
  1450.                /*
  1451.                 * All other prefix expressions are printed as the token
  1452.                 *  image of the operation followed by the operand.
  1453.                 */
  1454.                prt_tok(t, indent);
  1455.                c_walk(n->u[0].child, indent, 0);
  1456.                return 1;
  1457.             }
  1458.       case PstfxNd:
  1459.          /*
  1460.           * All postfix expressions are printed as the operand followed
  1461.           *  by the token image of the operation.
  1462.           */
  1463.          fall_thru = c_walk(n->u[0].child, indent, 0);
  1464.          prt_tok(t, indent);
  1465.          return fall_thru;
  1466.       case PreSpcNd:
  1467.          /*
  1468.           * This prefix expression (pointer indication in a declaration) needs
  1469.           *  a space after it.
  1470.           */
  1471.          prt_tok(t, indent);
  1472.          c_walk(n->u[0].child, indent, 0);
  1473.          prt_str(" ", indent);
  1474.          return 1;
  1475.       case SymNd:
  1476.          /*
  1477.           * Identifier.
  1478.           */
  1479.          prt_var(n, indent);
  1480.          return 1;
  1481.       case BinryNd:
  1482.          switch (t->tok_id) {
  1483.             case '[':
  1484.                /*
  1485.                 * subscripting expression or declaration: <expr> [ <expr> ]
  1486.                 */
  1487.                n1 = n->u[0].child;
  1488.                c_walk(n->u[0].child, indent, 0);
  1489.                prt_str("[", indent);
  1490.                c_walk(n->u[1].child, indent, 0);
  1491.                prt_str("]", indent);
  1492.                return 1;
  1493.             case '(':
  1494.                /*
  1495.                 * cast: ( <type> ) <expr>
  1496.                 */
  1497.                prt_tok(t, indent);  /* ) */
  1498.                c_walk(n->u[0].child, indent, 0);
  1499.                prt_str(")", indent);
  1500.                c_walk(n->u[1].child, indent, 0);
  1501.                return 1;
  1502.             case ')':
  1503.                /*
  1504.                 * function call or declaration: <expr> ( <expr-list> )
  1505.                 */
  1506.                c_walk(n->u[0].child, indent, 0);
  1507.                prt_str("(", indent);
  1508.                c_walk(n->u[1].child, indent, 0);
  1509.                prt_tok(t, indent);   /* ) */
  1510.                return call_ret(n->u[0].child);
  1511.             case Struct:
  1512.             case Union:
  1513.                /*
  1514.                 * struct/union <ident>
  1515.                 * struct/union <opt-ident> { <field-list> }
  1516.                 */
  1517.                prt_tok(t, indent);   /* struct or union */
  1518.                prt_str(" ", indent);
  1519.                c_walk(n->u[0].child, indent, 0);
  1520.                if (n->u[1].child != NULL) {
  1521.                   /*
  1522.                    * Field declaration list.
  1523.                    */
  1524.                   prt_str(" {", indent);
  1525.                   c_walk(n->u[1].child, indent + IndentInc, 0);
  1526.                   ForceNl();
  1527.                   prt_str("}", indent);
  1528.                   }
  1529.                return 1;
  1530.             case Enum:
  1531.                /*
  1532.                 * enum <ident>
  1533.                 * enum <opt-ident> { <enum-list> }
  1534.                 */
  1535.                prt_tok(t, indent);   /* enum */
  1536.                prt_str(" ", indent);
  1537.                c_walk(n->u[0].child, indent, 0);
  1538.                if (n->u[1].child != NULL) {
  1539.                   /*
  1540.                    * enumerator list.
  1541.                    */
  1542.                   prt_str(" {", indent);
  1543.                   c_walk(n->u[1].child, indent + IndentInc, 0);
  1544.                   prt_str("}", indent);
  1545.                   }
  1546.                return 1;
  1547.             case ';':
  1548.                /*
  1549.                 * <type-specs> <declarator> ;
  1550.                 */
  1551.                c_walk(n->u[0].child, indent, 0);
  1552.                prt_str(" ", indent);
  1553.                c_walk(n->u[1].child, indent, 0);
  1554.                prt_tok(t, indent);  /* ; */
  1555.                return 1;
  1556.             case ':':
  1557.                /*
  1558.                 * <label> : <statement>
  1559.                 */
  1560.                c_walk(n->u[0].child, indent, 0);
  1561.                prt_tok(t, indent);   /* : */
  1562.                prt_str(" ", indent);
  1563.                fall_thru = c_walk(n->u[1].child, indent, 0);
  1564.                may_brnchto = 1;
  1565.                return fall_thru;
  1566.             case Case:
  1567.                /*
  1568.                 * case <expr> : <statement>
  1569.                 */
  1570.                prt_tok(t, indent - IndentInc);  /* case (un-indented) */
  1571.                prt_str(" ", indent);
  1572.                c_walk(n->u[0].child, indent - IndentInc, 0);
  1573.                prt_str(": ", indent - IndentInc);
  1574.                fall_thru = c_walk(n->u[1].child, indent, 0);
  1575.                may_brnchto = 1;
  1576.                return fall_thru;
  1577.             case Switch:
  1578.                /*
  1579.                 * switch ( <expr> ) <statement>
  1580.                 *
  1581.                 * <statement> is double indented so that case and default
  1582.                 * statements can be un-indented and come out indented 1
  1583.                 * with respect to the switch. Statements that are not
  1584.                 * "labeled" with case or default are indented one more
  1585.                 * than those that are labeled.
  1586.                 */
  1587.                prt_tok(t, indent);  /* switch */
  1588.                prt_str(" (", indent);
  1589.                c_walk(n->u[0].child, indent, 0);
  1590.                prt_str(")", indent);
  1591.                prt_str(" ", indent);
  1592.                save_break = does_break;
  1593.                fall_thru = c_walk(n->u[1].child, indent + 2 * IndentInc, 0);
  1594.                fall_thru |= does_break;
  1595.                does_break = save_break;
  1596.                return fall_thru;
  1597.             case While: {
  1598.                struct node *n0;
  1599.                /*
  1600.                 * While ( <expr> ) <statement>
  1601.                 */
  1602.                n0 = n->u[0].child;
  1603.                prt_tok(t, indent);  /* while */
  1604.                prt_str(" (", indent);
  1605.                c_walk(n0, indent, 0);
  1606.                prt_str(")", indent);
  1607.                prt_str(" ", indent);
  1608.                save_break = does_break;
  1609.                c_walk(n->u[1].child, indent + IndentInc, 0);
  1610.                /*
  1611.                 * check for an infinite loop, while (1) ... :
  1612.                 *  a condition consisting of an IntConst with image=="1"
  1613.                 *  and no breaks in the body.
  1614.                 */
  1615.                if (n0->nd_id == PrimryNd && n0->tok->tok_id == IntConst &&
  1616.                    !strcmp(n0->tok->image,"1") && !does_break)
  1617.                   fall_thru = 0;
  1618.                else
  1619.                   fall_thru = 1;
  1620.                does_break = save_break;
  1621.                return fall_thru;
  1622.                }
  1623.             case Do:
  1624.                /*
  1625.                 * do <statement> <while> ( <expr> )
  1626.                 */
  1627.                prt_tok(t, indent);  /* do */
  1628.                prt_str(" ", indent);
  1629.                c_walk(n->u[0].child, indent + IndentInc, 0);
  1630.                ForceNl();
  1631.                prt_str("while (", indent);
  1632.                save_break = does_break;
  1633.                c_walk(n->u[1].child, indent, 0);
  1634.                does_break = save_break;
  1635.                prt_str(");", indent);
  1636.                return 1;
  1637.             case '.':
  1638.             case Arrow:
  1639.                /*
  1640.                 * Field access: <expr> . <expr>  and  <expr> -> <expr>
  1641.                 */
  1642.                c_walk(n->u[0].child, indent, 0);
  1643.                prt_tok(t, indent);   /* . or -> */
  1644.                c_walk(n->u[1].child, indent, 0);
  1645.                return 1;
  1646.             case Runerr:
  1647.                /*
  1648.                 * runerr ( <error-number> )
  1649.                 * runerr ( <error-number> , <offending-value> )
  1650.                 */
  1651.                prt_runerr(t, n->u[0].child, n->u[1].child, indent);
  1652.                return 0;
  1653.             case Is:
  1654.                /*
  1655.                 * is : <type> ( <expr> )
  1656.                 */
  1657.                typ_asrt(icn_typ(n->u[0].child), n->u[1].child,
  1658.                   n->u[0].child->tok, indent);
  1659.                return 1;
  1660.             default:
  1661.                /*
  1662.                 * All other binary expressions are infix notation and
  1663.                 *  are printed with spaces around the operator.
  1664.                 */
  1665.                c_walk(n->u[0].child, indent, 0);
  1666.                prt_str(" ", indent);
  1667.                prt_tok(t, indent);
  1668.                prt_str(" ", indent);
  1669.                c_walk(n->u[1].child, indent, 0);
  1670.                return 1;
  1671.             }
  1672.       case LstNd:
  1673.          /*
  1674.           * <declaration-part> <declaration-part>
  1675.           *
  1676.           * Need space between parts
  1677.           */
  1678.          c_walk(n->u[0].child, indent, 0);
  1679.          prt_str(" ", indent);
  1680.          c_walk(n->u[1].child, indent, 0);
  1681.          return 1;
  1682.       case ConCatNd:
  1683.          /*
  1684.           * <some-code> <some-code>
  1685.           *
  1686.           * Various lists of code parts that do not need space between them.
  1687.           */
  1688.          if (c_walk(n->u[0].child, indent, 0))
  1689.             return c_walk(n->u[1].child, indent, 0);
  1690.          else {
  1691.             /*
  1692.              * Cannot directly reach the second piece of code, see if
  1693.              *  it is possible to branch into it.
  1694.              */
  1695.             may_brnchto = 0;
  1696.             fall_thru = c_walk(n->u[1].child, indent, 0);
  1697.             return may_brnchto & fall_thru;
  1698.             }
  1699.       case CommaNd:
  1700.          /*
  1701.           * <expr> , <expr>
  1702.           */
  1703.          c_walk(n->u[0].child, indent, 0);
  1704.          prt_tok(t, indent);
  1705.          prt_str(" ", indent);
  1706.          return c_walk(n->u[1].child, indent, 0);
  1707.       case StrDclNd:
  1708.          /*
  1709.           * Structure field declaration. Bit field declarations have
  1710.           *  a semicolon and a field width.
  1711.           */
  1712.          c_walk(n->u[0].child, indent, 0);
  1713.          if (n->u[1].child != NULL) {
  1714.             prt_str(": ", indent);
  1715.             c_walk(n->u[1].child, indent, 0);
  1716.             }
  1717.          return 1;
  1718.       case CompNd:
  1719.          /*
  1720.           * Compound statement.
  1721.           */
  1722.          if (brace)
  1723.             tok_line(t, indent); /* just synch. file name and line number */
  1724.          else
  1725.             prt_tok(t, indent);  /* { */
  1726.          c_walk(n->u[0].child, indent, 0);
  1727.          /*
  1728.           * we are in an inner block. tended locations may need to
  1729.           *  be set to values from declaration initializations.
  1730.           */
  1731.          for (sym = n->u[1].sym; sym!= NULL; sym = sym->u.tnd_var.next) {
  1732.             if (sym->u.tnd_var.init != NULL) {
  1733.                prt_str(tendstrct, IndentInc);
  1734.                fprintf(out_file, ".d[%d]", sym->t_indx);
  1735.                switch (sym->id_type) {
  1736.                   case TndDesc:
  1737.                      prt_str(" = ", IndentInc);
  1738.                      break;
  1739.                   case TndStr:
  1740.                      prt_str(".vword.sptr = ", IndentInc);
  1741.                      break;
  1742.                   case TndBlk:
  1743.                      prt_str(".vword.bptr = (union block *)",
  1744.                         IndentInc);
  1745.                      break;
  1746.                   }
  1747.                c_walk(sym->u.tnd_var.init, 2 * IndentInc, 0);
  1748.                prt_str(";", 2 * IndentInc);
  1749.                ForceNl();
  1750.                }
  1751.             }
  1752.          /*
  1753.           * If there are no declarations, suppress braces that
  1754.           *  may be required for a one-statement body; we already
  1755.           *  have a set.
  1756.           */
  1757.          if (n->u[0].child == NULL && n->u[1].sym == NULL)
  1758.             fall_thru = c_walk(n->u[2].child, indent, 1);
  1759.          else
  1760.             fall_thru = c_walk(n->u[2].child, indent, 0);
  1761.          if (!brace) {
  1762.             ForceNl();
  1763.             prt_str("}", indent);
  1764.             }
  1765.          return fall_thru;
  1766.       case TrnryNd:
  1767.          switch (t->tok_id) {
  1768.             case '?':
  1769.                /*
  1770.                 * <expr> ? <expr> : <expr>
  1771.                 */
  1772.                c_walk(n->u[0].child, indent, 0);
  1773.                prt_str(" ", indent);
  1774.                prt_tok(t, indent);  /* ? */
  1775.                prt_str(" ", indent);
  1776.                c_walk(n->u[1].child, indent, 0);
  1777.                prt_str(" : ", indent);
  1778.                c_walk(n->u[2].child, indent, 0);
  1779.                return 1;
  1780.             case If:
  1781.                /*
  1782.                 * if ( <expr> ) <statement>
  1783.                 * if ( <expr> ) <statement> else <statement>
  1784.                 */
  1785.                prt_tok(t, indent);  /* if */
  1786.                prt_str(" (", indent);
  1787.                c_walk(n->u[0].child, indent + IndentInc, 0);
  1788.                prt_str(") ", indent);
  1789.                fall_thru = c_walk(n->u[1].child, indent + IndentInc, 0);
  1790.                n1 = n->u[2].child;
  1791.                if (n1 == NULL)
  1792.                   fall_thru = 1;
  1793.                else {
  1794.                   /*
  1795.                    * There is an else statement. Don't indent an
  1796.                    *  "else if"
  1797.                    */
  1798.                   ForceNl();
  1799.                   prt_str("else ", indent);
  1800.                   if (n1->nd_id == TrnryNd && n1->tok->tok_id == If)
  1801.                      fall_thru |= c_walk(n1, indent, 0);
  1802.                   else
  1803.                      fall_thru |= c_walk(n1, indent + IndentInc, 0);
  1804.                   }
  1805.                return fall_thru;
  1806.             case Type_case:
  1807.                /*
  1808.                 * type_case <expr> of { <section-list> }
  1809.                 * type_case <expr> of { <section-list> <default-clause> }
  1810.                 */
  1811.                return typ_case(n->u[0].child, n->u[1].child, n->u[2].child,
  1812.                   c_walk, 1, indent);
  1813.             case Cnv:
  1814.                /*
  1815.                 * cnv : <type> ( <source> , <destination> )
  1816.                 */
  1817.                cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, NULL,
  1818.                   n->u[2].child,
  1819.                   indent);
  1820.                return 1;
  1821.             }
  1822.       case QuadNd:
  1823.          switch (t->tok_id) {
  1824.             case For:
  1825.                /*
  1826.                 * for ( <expr> ; <expr> ; <expr> ) <statement>
  1827.                 */
  1828.                prt_tok(t, indent);  /* for */
  1829.                prt_str(" (", indent);
  1830.                c_walk(n->u[0].child, indent, 0);
  1831.                prt_str("; ", indent);
  1832.                c_walk(n->u[1].child, indent, 0);
  1833.                prt_str("; ", indent);
  1834.                c_walk(n->u[2].child, indent, 0);
  1835.                prt_str(") ", indent);
  1836.                save_break = does_break;
  1837.                c_walk(n->u[3].child, indent + IndentInc, 0);
  1838.                if (n->u[1].child == NULL && !does_break)
  1839.                   fall_thru = 0;
  1840.                else
  1841.                   fall_thru = 1;
  1842.                does_break = save_break;
  1843.                return fall_thru;
  1844.             case Def:
  1845.                /*
  1846.                 * def : <type> ( <source> , <default> , <destination> )
  1847.                 */
  1848.                cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, n->u[2].child,
  1849.                   n->u[3].child, indent);
  1850.                return 1;
  1851.             }
  1852.       }
  1853.    }
  1854.  
  1855. /*
  1856.  * call_ret - decide whether a function being called might return.
  1857.  */
  1858. int call_ret(n)
  1859. struct node *n;
  1860.    {
  1861.    /*
  1862.     * Assume functions return except for c_exit(), fatalerr(), and syserr().
  1863.     */
  1864.    if (n->tok != NULL &&
  1865.       (strcmp("c_exit",   n->tok->image) == 0 ||
  1866.        strcmp("fatalerr", n->tok->image) == 0 ||
  1867.        strcmp("syserr",   n->tok->image) == 0))
  1868.       return 0;
  1869.    else
  1870.       return 1;
  1871.    }
  1872.  
  1873. /*
  1874.  * new_prmloc - allocate an array large enough to hold a flag for every
  1875.  *  parameter of the current operation. This flag indicates where
  1876.  *  the parameter is in terms of scopes created by conversions.
  1877.  */
  1878. struct parminfo *new_prmloc()
  1879.    {
  1880.    struct parminfo *parminfo;
  1881.    int nparams;
  1882.    int i;
  1883.  
  1884.    if (params == NULL)
  1885.       return NULL;
  1886.    nparams = params->u.param_info.param_num + 1;
  1887.    parminfo = (struct parminfo *)alloc((unsigned)nparams *
  1888.      sizeof(struct parminfo));
  1889.    for (i = 0; i < nparams; ++i) {
  1890.       parminfo[i].cur_loc = 0;
  1891.       parminfo [i].parm_mod = 0;
  1892.       }
  1893.    return parminfo;
  1894.    }
  1895.  
  1896. /*
  1897.  * ld_prmloc - load parameter location information that has been
  1898.  *  saved in an arrary into the symbol table.
  1899.  */
  1900. novalue ld_prmloc(parminfo)
  1901. struct parminfo *parminfo;
  1902.    {
  1903.    struct sym_entry *sym;
  1904.    int param_num;
  1905.  
  1906.    for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
  1907.       param_num = sym->u.param_info.param_num;
  1908.       if (sym->id_type & DrfPrm) {
  1909.          sym->u.param_info.cur_loc = parminfo[param_num].cur_loc;
  1910.          sym->u.param_info.parm_mod = parminfo[param_num].parm_mod;
  1911.          }
  1912.       }
  1913.    }
  1914.  
  1915. /*
  1916.  * sv_prmloc - save parameter location information from the the symbol table
  1917.  *  into an array.
  1918.  */
  1919. novalue sv_prmloc(parminfo)
  1920. struct parminfo *parminfo;
  1921.    {
  1922.    struct sym_entry *sym;
  1923.    int param_num;
  1924.  
  1925.    for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
  1926.       param_num = sym->u.param_info.param_num;
  1927.       if (sym->id_type & DrfPrm) {
  1928.          parminfo[param_num].cur_loc = sym->u.param_info.cur_loc;
  1929.          parminfo[param_num].parm_mod = sym->u.param_info.parm_mod;
  1930.          }
  1931.       }
  1932.    }
  1933.  
  1934. /*
  1935.  * mrg_prmloc - merge parameter location information in the symbol table
  1936.  *  with other information already saved in an array. This may result
  1937.  *  in conflicting location information, but conflicts are only detected
  1938.  *  when a parameter is actually used.
  1939.  */
  1940. novalue mrg_prmloc(parminfo)
  1941. struct parminfo *parminfo;
  1942.    {
  1943.    struct sym_entry *sym;
  1944.    int param_num;
  1945.  
  1946.    for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
  1947.       param_num = sym->u.param_info.param_num;
  1948.       if (sym->id_type & DrfPrm) {
  1949.          parminfo[param_num].cur_loc |= sym->u.param_info.cur_loc;
  1950.          parminfo[param_num].parm_mod |= sym->u.param_info.parm_mod;
  1951.          }
  1952.       }
  1953.    }
  1954.  
  1955. /*
  1956.  * clr_prmloc - indicate that this execution path contributes nothing
  1957.  *   to the location of parameters.
  1958.  */
  1959. novalue clr_prmloc()
  1960.    {
  1961.    struct sym_entry *sym;
  1962.  
  1963.    for (sym = params; sym != NULL; sym = sym->u.param_info.next) {
  1964.       if (sym->id_type & DrfPrm) {
  1965.          sym->u.param_info.cur_loc = 0;
  1966.          sym->u.param_info.parm_mod = 0;
  1967.          }
  1968.       }
  1969.    }
  1970.  
  1971. /*
  1972.  * typ_case - translate a type_case statement into C. This is called
  1973.  *  while walking a syntax tree of either RTL code or C code; the parameter
  1974.  *  "walk" is a function used to process the subtrees within the type_case
  1975.  *  statement.
  1976.  */
  1977. static int typ_case(var, slct_lst, dflt, walk, maybe_var, indent)
  1978. struct node *var;
  1979. struct node *slct_lst;
  1980. struct node *dflt;
  1981. int (*walk)Params((struct node *n, int indent, int brace));
  1982. int maybe_var;
  1983. int indent;
  1984.    {
  1985.    struct node *lst;
  1986.    struct node *select;
  1987.    struct node *slctor;
  1988.    struct parminfo *strt_prms;
  1989.    struct parminfo *end_prms;
  1990.    int remaining;
  1991.    int first;
  1992.    int fnd_slctrs;
  1993.    int maybe_str = 1;
  1994.    int dflt_lbl;
  1995.    int typcd;
  1996.    int fall_thru;
  1997.    char *s;
  1998.  
  1999.    /*
  2000.     * This statement involves multiple paths that may establish new
  2001.     *  scopes for parameters. Remember the starting scope information
  2002.     *  and initialize an array in which to compute the final information.
  2003.     */
  2004.    strt_prms = new_prmloc();
  2005.    sv_prmloc(strt_prms);
  2006.    end_prms = new_prmloc();
  2007.  
  2008.    /*
  2009.     * First look for cases that must be checked with "if" statements.
  2010.     *  These include string qualifiers and variables.
  2011.     */
  2012.    remaining = 0;      /* number of cases skipped in first pass */
  2013.    first = 1;          /* next case to be output is the first */
  2014.    if (dflt == NULL)
  2015.       fall_thru = 1;
  2016.    else
  2017.       fall_thru = 0;
  2018.    for (lst = slct_lst; lst != NULL; lst = lst->u[0].child) {
  2019.       select = lst->u[1].child;
  2020.       fnd_slctrs = 0; /* flag: found type selections for clause for this pass */
  2021.       /*
  2022.        * A selection clause may include several types. 
  2023.        */
  2024.       for (slctor = select->u[0].child; slctor != NULL; slctor =
  2025.         slctor->u[0].child) {
  2026.          typcd = icn_typ(slctor->u[1].child);
  2027.          if(typ_name(typcd, slctor->u[1].child->tok) == NULL) {
  2028.             /*
  2029.              * This type must be checked with the "if". Is this the
  2030.              *  first condition checked for this clause? Is this the
  2031.              *  first clause output?
  2032.              */
  2033.             if (fnd_slctrs)
  2034.                prt_str(" || ", indent);
  2035.             else {
  2036.                if (first)
  2037.                   first = 0;
  2038.                else {
  2039.                   ForceNl();
  2040.                   prt_str("else ", indent);
  2041.                   }
  2042.                prt_str("if (", indent);
  2043.                fnd_slctrs = 1;
  2044.                }
  2045.             
  2046.             /*
  2047.              * Output type check
  2048.              */
  2049.             typ_asrt(typcd, var, slctor->u[1].child->tok, indent + IndentInc);
  2050.  
  2051.             if (typcd == str_typ)
  2052.                maybe_str = 0;  /* string has been taken care of */
  2053.             else if (typcd == Variable)
  2054.                maybe_var = 0;  /* variable has been taken care of */
  2055.             }
  2056.          else
  2057.             ++remaining;
  2058.          }
  2059.       if (fnd_slctrs) {
  2060.          /*
  2061.           * We have found and output type selections for this clause;
  2062.           *  output the body of the clause. Remember any changes to
  2063.           *  paramter locations caused by type conversions within the
  2064.           *  clause.
  2065.           */
  2066.          prt_str(") {", indent + IndentInc);
  2067.          ForceNl();
  2068.          if ((*walk)(select->u[1].child, indent + IndentInc, 1)) {
  2069.             fall_thru |= 1;
  2070.             mrg_prmloc(end_prms);
  2071.             }
  2072.          prt_str("}", indent + IndentInc);
  2073.          ForceNl();
  2074.          ld_prmloc(strt_prms);
  2075.          }
  2076.       }
  2077.    /*
  2078.     * The rest of the cases can be checked with a "switch" statement, look
  2079.     *  for them..
  2080.     */
  2081.    if (remaining == 0) {
  2082.       if (dflt != NULL) {
  2083.          /*
  2084.           * There are no cases to handle with a switch statement, but there
  2085.           *  is a default clause; handle it with an "else".
  2086.           */
  2087.          prt_str("else {", indent);
  2088.          ForceNl();
  2089.          fall_thru |= (*walk)(dflt, indent + IndentInc, 1);
  2090.          ForceNl();
  2091.          prt_str("}", indent + IndentInc);
  2092.          ForceNl();
  2093.          }
  2094.       }
  2095.    else {
  2096.       /*
  2097.        * If an "if" statement was output, the "switch" must be in its "else"
  2098.        *   clause.
  2099.        */
  2100.       if (!first)
  2101.          prt_str("else ", indent);
  2102.  
  2103.       /*
  2104.        * A switch statement cannot handle types that are not simple type
  2105.        *  codes. If these have not taken care of, output code to check them.
  2106.        *  This will either branch around the switch statement or into
  2107.        *  its default clause.
  2108.        */
  2109.       if (maybe_str || maybe_var) {
  2110.          dflt_lbl = lbl_num++;      /* allocate a label number */
  2111.          prt_str("{", indent);
  2112.          ForceNl();
  2113.          prt_str("if (((", indent);
  2114.          c_walk(var, indent + IndentInc, 0);
  2115.          prt_str(").dword & D_Typecode) != D_Typecode) ", indent);
  2116.          ForceNl();
  2117.          prt_str("goto L", indent + IndentInc);
  2118.          fprintf(out_file, "%d;  /* default */ ", dflt_lbl);
  2119.          ForceNl();
  2120.          }
  2121.  
  2122.       no_nl = 1; /* suppress #line directives */
  2123.       prt_str("switch (Type(", indent);
  2124.       c_walk(var, indent + IndentInc, 0);
  2125.       prt_str(")) {", indent + IndentInc);
  2126.       no_nl = 0;
  2127.       ForceNl();
  2128.  
  2129.       /*
  2130.        * Loop through the case clauses producing code for them.
  2131.        */
  2132.       for (lst = slct_lst; lst != NULL; lst = lst->u[0].child) {
  2133.          select = lst->u[1].child;
  2134.          fnd_slctrs = 0;
  2135.          /*
  2136.           * A selection clause may include several types. 
  2137.           */
  2138.          for (slctor = select->u[0].child; slctor != NULL; slctor =
  2139.            slctor->u[0].child) {
  2140.             typcd = icn_typ(slctor->u[1].child);
  2141.             s = typ_name(typcd, slctor->u[1].child->tok);
  2142.             if (s != NULL) {
  2143.                /*
  2144.                 * A type selection has been found that can be checked
  2145.                 *  in the switch statement. Note that large integers
  2146.                 *  require special handling.
  2147.                 */
  2148.                fnd_slctrs = 1;
  2149.  
  2150.            if (typcd == int_typ) {
  2151.          ForceNl();
  2152.          prt_str("#ifdef LargeInts", 0);
  2153.          ForceNl();
  2154.          prt_str("case T_Lrgint:  ", indent + IndentInc);
  2155.          ForceNl();
  2156.          prt_str("#endif /* LargeInts */", 0);
  2157.          ForceNl();
  2158.            }
  2159.  
  2160.                prt_str("case T_", indent + IndentInc);
  2161.                prt_str(s, indent + IndentInc);
  2162.                prt_str(": ", indent + IndentInc);
  2163.                }
  2164.             }
  2165.          if (fnd_slctrs) {
  2166.             /*
  2167.              * We have found and output type selections for this clause;
  2168.              *  output the body of the clause. Remember any changes to
  2169.              *  paramter locations caused by type conversions within the
  2170.              *  clause.
  2171.              */
  2172.             ForceNl();
  2173.             if ((*walk)(select->u[1].child, indent + 2 * IndentInc, 0)) {
  2174.                fall_thru |= 1;
  2175.                ForceNl();
  2176.                prt_str("break;", indent + 2 * IndentInc);
  2177.                mrg_prmloc(end_prms);
  2178.                }
  2179.             ForceNl();
  2180.             ld_prmloc(strt_prms);
  2181.             }
  2182.          }
  2183.       if (dflt != NULL) {
  2184.          /*
  2185.           * This type_case statement has a default clause. If there is
  2186.           *  a branch into this clause, output the label. Remember any
  2187.           *  changes to paramter locations caused by type conversions
  2188.           *  within the clause.
  2189.           */
  2190.          ForceNl();
  2191.          prt_str("default:", indent + 1 * IndentInc);
  2192.          ForceNl();
  2193.          if (maybe_str || maybe_var) {
  2194.             prt_str("L", 0);
  2195.             fprintf(out_file, "%d: ;  /* default */", dflt_lbl);
  2196.             ForceNl();
  2197.             }
  2198.          if ((*walk)(dflt, indent + 2 * IndentInc, 0)) {
  2199.             fall_thru |= 1;
  2200.             mrg_prmloc(end_prms);
  2201.             }
  2202.          ForceNl();
  2203.          ld_prmloc(strt_prms);
  2204.          }
  2205.       prt_str("}", indent + IndentInc);
  2206.  
  2207.       if (maybe_str || maybe_var) {
  2208.          if (dflt == NULL) {
  2209.             /*
  2210.              * There is a branch around the switch statement. Output
  2211.              *  the label.
  2212.              */
  2213.             ForceNl();
  2214.             prt_str("L", 0);
  2215.             fprintf(out_file, "%d: ;  /* default */", dflt_lbl);
  2216.             }
  2217.          ForceNl();
  2218.          prt_str("}", indent + IndentInc);
  2219.          }
  2220.       ForceNl();
  2221.       }
  2222.  
  2223.    /*
  2224.     * Put ending parameter locations into effect.
  2225.     */
  2226.    mrg_prmloc(end_prms);
  2227.    ld_prmloc(end_prms);
  2228.    if (strt_prms != NULL)
  2229.       free(strt_prms);
  2230.    if (end_prms != NULL)
  2231.       free(end_prms);
  2232.    return fall_thru;
  2233.    }
  2234.  
  2235. /*
  2236.  * chk_conj - see if the left argument of a conjunction is an in-place
  2237.  *   conversion of a parameter other than a conversion to C_integer or
  2238.  *   C_double. If so issue a warning.
  2239.  */
  2240. static novalue chk_conj(n)
  2241. struct node *n;
  2242.    {
  2243.    struct node *cnv_type;
  2244.    struct node *src;
  2245.    struct node *dest;
  2246.    int typcd;
  2247.  
  2248.    if (n->nd_id == BinryNd && n->tok->tok_id == And)
  2249.       n = n->u[1].child;
  2250.  
  2251.    switch (n->nd_id) {
  2252.       case TrnryNd:
  2253.          /*
  2254.           * Must be Cnv.
  2255.           */
  2256.          cnv_type = n->u[0].child;
  2257.          src = n->u[1].child;
  2258.          dest = n->u[2].child;
  2259.          break;
  2260.       case QuadNd:
  2261.          /*
  2262.           * Must be Def.
  2263.           */
  2264.          cnv_type = n->u[0].child;
  2265.          src = n->u[1].child;
  2266.          dest = n->u[3].child;
  2267.          break;
  2268.       default:
  2269.          return;   /* not a  conversion */
  2270.       }
  2271.  
  2272.    /*
  2273.     * A conversion has been found. See if it meets the criteria for
  2274.     *  issuing a warning.
  2275.     */
  2276.  
  2277.    if (src->nd_id != SymNd || !(src->u[0].sym->id_type & DrfPrm))
  2278.       return;  /* not a dereferenced parameter */
  2279.  
  2280.    typcd = icn_typ(cnv_type);
  2281.    switch (typcd) {
  2282.       case TypCInt:
  2283.       case TypCDbl:
  2284.       case TypECInt:
  2285.          return;
  2286.       }
  2287.  
  2288.    if (dest != NULL)
  2289.       return;   /* not an in-place convertion */
  2290.  
  2291.    fprintf(stderr,
  2292.     "%s: file %s, line %d, warning: in-place conversion may or may not be\n",
  2293.       progname, cnv_type->tok->fname, cnv_type->tok->line);
  2294.    fprintf(stderr, "\tundone on subsequent failure.\n");
  2295.    }
  2296.  
  2297. /*
  2298.  * len_sel - translate a clause form a len_case statement into a C case
  2299.  *  clause. Return an indication of whether execution falls through the
  2300.  *  clause.
  2301.  */
  2302. static int len_sel(sel, strt_prms, end_prms, indent)
  2303. struct node *sel;
  2304. struct parminfo *strt_prms;
  2305. struct parminfo *end_prms;
  2306. int indent;
  2307.    {
  2308.    int fall_thru;
  2309.  
  2310.    prt_str("case ", indent);
  2311.    prt_tok(sel->tok, indent + IndentInc);           /* integer selection */
  2312.    prt_str(":", indent + IndentInc);
  2313.    fall_thru = rt_walk(sel->u[0].child, indent + IndentInc, 0);/* clause body */
  2314.    ForceNl();
  2315.  
  2316.    if (fall_thru) {
  2317.       prt_str("break;", indent + IndentInc);
  2318.       ForceNl();
  2319.       /*
  2320.        * Remember any changes to paramter locations caused by type conversions
  2321.        *  within the clause.
  2322.        */
  2323.       mrg_prmloc(end_prms);
  2324.       }
  2325.  
  2326.    ld_prmloc(strt_prms);
  2327.    return fall_thru;
  2328.    }
  2329.  
  2330. /*
  2331.  * rt_walk - walk the part of the syntax tree containing rtt code, producing
  2332.  *   code for the most-general version of the routine.
  2333.  */
  2334. static int rt_walk(n, indent, brace)
  2335. struct node *n;
  2336. int indent;
  2337. int brace;
  2338.    {
  2339.    struct token *t, *t1;
  2340.    struct node *n1, *errnum;
  2341.    struct sym_entry *sym;
  2342.    int fall_thru;
  2343.  
  2344.    if (n == NULL)
  2345.       return 1;
  2346.  
  2347.    t =  n->tok;
  2348.  
  2349.    switch (n->nd_id) {
  2350.       case PrefxNd:
  2351.          switch (t->tok_id) {
  2352.             case '{':
  2353.                /*
  2354.                 * RTL code: { <actions> }
  2355.                 */
  2356.                if (brace) 
  2357.                   tok_line(t, indent); /* just synch file name and line num */
  2358.                else
  2359.                   prt_tok(t, indent);  /* { */
  2360.                fall_thru = rt_walk(n->u[0].child, indent, 1);
  2361.                if (!brace)
  2362.                   prt_str("}", indent);
  2363.                return fall_thru;
  2364.             case '!':
  2365.                /*
  2366.                 * RTL type-checking and conversions: ! <simple-type-check>
  2367.                 */
  2368.                prt_tok(t, indent);
  2369.                rt_walk(n->u[0].child, indent, 0);
  2370.                return 1;
  2371.             case Body:
  2372.             case Inline:
  2373.                /*
  2374.                 * RTL code: body { <c-code> }
  2375.                 *           inline { <c-code> }
  2376.                 */
  2377.                fall_thru = c_walk(n->u[0].child, indent, brace);
  2378.                if (!fall_thru)
  2379.                   clr_prmloc();
  2380.                return fall_thru;
  2381.             }
  2382.          break;
  2383.       case BinryNd:
  2384.          switch (t->tok_id) {
  2385.             case Runerr:
  2386.                /*
  2387.                 * RTL code: runerr( <message-number> )
  2388.                 *           runerr( <message-number>, <descriptor> )
  2389.                 */
  2390.                prt_runerr(t, n->u[0].child, n->u[1].child, indent);
  2391.  
  2392.                /*
  2393.                 * Execution cannot continue on this execution path.
  2394.                 */
  2395.                clr_prmloc();
  2396.                return 0;
  2397.             case And:
  2398.                /*
  2399.                 * RTL type-checking and conversions:
  2400.                 *   <type-check> && <type_check>
  2401.                 */
  2402.                chk_conj(n->u[0].child);  /* is a warning needed? */
  2403.                rt_walk(n->u[0].child, indent, 0);
  2404.                prt_str(" ", indent);
  2405.                prt_tok(t, indent);       /* && */
  2406.                prt_str(" ", indent);
  2407.                rt_walk(n->u[1].child, indent, 0);
  2408.                return 1;
  2409.             case Is:
  2410.                /*
  2411.                 * RTL type-checking and conversions:
  2412.                 *   is: <icon-type> ( <variable> )
  2413.                 */
  2414.                typ_asrt(icn_typ(n->u[0].child), n->u[1].child,
  2415.                   n->u[0].child->tok, indent);
  2416.                return 1;
  2417.             }
  2418.          break;
  2419.       case ConCatNd:
  2420.          /*
  2421.           * "Glue" for two constructs.
  2422.           */
  2423.          fall_thru = rt_walk(n->u[0].child, indent, 0);
  2424.          return fall_thru & rt_walk(n->u[1].child, indent, 0);
  2425.       case AbstrNd:
  2426.          /*
  2427.           * Ignore abstract type computations while producing C code
  2428.           *  for library routines.
  2429.           */
  2430.          return 1;
  2431.       case TrnryNd:
  2432.          switch (t->tok_id) {
  2433.             case If: {
  2434.                /*
  2435.                 * RTL code for "if" statements:
  2436.                 *  if <type-check> then <action>
  2437.                 *  if <type-check> then <action> else <action>
  2438.                 *
  2439.                 *  <type-check> may include parameter conversions that create
  2440.                 *  new scoping. It is necessary to keep track of paramter
  2441.                 *  types and locations along success and failure paths of
  2442.                 *  these conversions. The "then" and "else" actions may
  2443.                 *  also establish new scopes.
  2444.                 */
  2445.                struct parminfo *then_prms = NULL;
  2446.                struct parminfo *else_prms;
  2447.  
  2448.                /*
  2449.                 * Save the current parameter locations. These are in
  2450.                 *  effect on the failure path of any type conversions
  2451.                 *  in the condition of the "if".
  2452.                 */
  2453.                else_prms = new_prmloc();
  2454.                sv_prmloc(else_prms);
  2455.  
  2456.                prt_tok(t, indent);       /* if */
  2457.                prt_str(" (", indent);
  2458.                n1 = n->u[0].child;
  2459.                rt_walk(n1, indent + IndentInc, 0);   /* type check */
  2460.                prt_str(") {", indent);
  2461.  
  2462.                /*
  2463.                 * If the condition is negated, the failure path is to the "then"
  2464.                 *  and the success path is to the "else".
  2465.                 */
  2466.                if (n1->nd_id == PrefxNd && n1->tok->tok_id == '!') {
  2467.                   then_prms = else_prms;
  2468.                   else_prms = new_prmloc();
  2469.                   sv_prmloc(else_prms);
  2470.                   ld_prmloc(then_prms);
  2471.                   }
  2472.  
  2473.                /*
  2474.                 * Then Clause.
  2475.                 */
  2476.                fall_thru = rt_walk(n->u[1].child, indent + IndentInc, 1);
  2477.                ForceNl();
  2478.                prt_str("}", indent + IndentInc);
  2479.  
  2480.                /*
  2481.                 * Determine if there is an else clause and merge parameter
  2482.                 *  location information from the alternate paths through
  2483.                 *  the statement.
  2484.                 */
  2485.                n1 = n->u[2].child;
  2486.                if (n1 == NULL) {
  2487.                   if (fall_thru)
  2488.                      mrg_prmloc(else_prms);
  2489.                   ld_prmloc(else_prms);
  2490.                   fall_thru = 1;
  2491.                   }
  2492.                else {
  2493.                   if (then_prms == NULL)
  2494.                      then_prms = new_prmloc();
  2495.                   if (fall_thru)
  2496.                      sv_prmloc(then_prms);
  2497.                   ld_prmloc(else_prms);
  2498.                   ForceNl();
  2499.                   prt_str("else {", indent);
  2500.                   if (rt_walk(n1, indent + IndentInc, 1)) {  /* else clause */
  2501.                      fall_thru = 1;
  2502.                      mrg_prmloc(then_prms);
  2503.                      }
  2504.                   ForceNl();
  2505.                   prt_str("}", indent + IndentInc);
  2506.                   ld_prmloc(then_prms);
  2507.                   }
  2508.                ForceNl();
  2509.                if (then_prms != NULL)
  2510.                   free(then_prms);
  2511.                if (else_prms != NULL)
  2512.                   free(else_prms);
  2513.                }
  2514.                return fall_thru;
  2515.             case Len_case: {
  2516.                /*
  2517.                 * RTL code:
  2518.                 *   len_case <variable> of {
  2519.                 *      <integer>: <action>
  2520.                 *        ...
  2521.                 *      default: <action>
  2522.                 *      }
  2523.                 */
  2524.                struct parminfo *strt_prms;
  2525.                struct parminfo *end_prms;
  2526.  
  2527.                /*
  2528.                 * A case may contain parameter conversions that create new
  2529.                 *  scopes. Remember the parameter locations at the start
  2530.                 *  of the len_case statement.
  2531.                 */
  2532.                strt_prms = new_prmloc();
  2533.                sv_prmloc(strt_prms);
  2534.                end_prms = new_prmloc();
  2535.  
  2536.                n1 = n->u[0].child;
  2537.                if (!(n1->u[0].sym->id_type & VArgLen))
  2538.                   errt1(t, "len_case must select on length of vararg");
  2539.  
  2540.                /*
  2541.                 * The len_case statement is implemented as a C switch
  2542.                 *  statement.
  2543.                 */
  2544.                prt_str("switch (", indent);
  2545.                prt_var(n1, indent);
  2546.                prt_str(") {", indent);
  2547.                ForceNl();
  2548.                fall_thru = 0;
  2549.                for (n1 = n->u[1].child; n1->nd_id == ConCatNd;
  2550.                   n1 = n1->u[0].child)
  2551.                      fall_thru |= len_sel(n1->u[1].child, strt_prms, end_prms,
  2552.                         indent + IndentInc);
  2553.                fall_thru |= len_sel(n1, strt_prms, end_prms,
  2554.                   indent + IndentInc);
  2555.  
  2556.                /*
  2557.                 * Handle default clause.
  2558.                 */
  2559.                prt_str("default:", indent + IndentInc);
  2560.                ForceNl();
  2561.                fall_thru |= rt_walk(n->u[2].child, indent + 2 * IndentInc, 0);
  2562.                ForceNl();
  2563.                prt_str("}", indent + IndentInc);
  2564.                ForceNl();
  2565.  
  2566.                /*
  2567.                 * Put into effect the location of parameters at the end
  2568.                 *  of the len_case statement.
  2569.                 */
  2570.                mrg_prmloc(end_prms);
  2571.                ld_prmloc(end_prms);
  2572.                if (strt_prms != NULL)
  2573.                   free(strt_prms);
  2574.                if (end_prms != NULL)
  2575.                   free(end_prms);
  2576.                }
  2577.                return fall_thru;
  2578.             case Type_case: {
  2579.                /*
  2580.                 * RTL code:
  2581.                 *   type_case <variable> of {
  2582.                 *       <icon_type> : ... <icon_type> : <action>
  2583.                 *          ...
  2584.                 *       }
  2585.                 *
  2586.                 *   last clause may be: default: <action>
  2587.                 */
  2588.                int maybe_var;
  2589.                struct node *var;
  2590.                struct sym_entry *sym;
  2591.  
  2592.                /*
  2593.                 * If we can determine that the value being checked is
  2594.                 *  not a variable reference, we don't have to produce code
  2595.                 *  to check for that possibility.
  2596.                 */
  2597.                maybe_var = 1;
  2598.                var = n->u[0].child;
  2599.                if (var->nd_id == SymNd) {
  2600.                   sym = var->u[0].sym;
  2601.                   switch(sym->id_type) {
  2602.                      case DrfPrm:
  2603.                      case OtherDcl:
  2604.                      case TndDesc:
  2605.                      case TndStr:
  2606.                      case RsltLoc:
  2607.                         if (sym->nest_lvl > 1) {
  2608.                            /*
  2609.                             * The thing being tested is either a
  2610.                             *  dereferenced parameter or a local
  2611.                             *  descriptor which could only have been
  2612.                             *  set by a conversion which does not
  2613.                             *  produce a variable reference.
  2614.                             */
  2615.                            maybe_var = 0;
  2616.                            }
  2617.                       }
  2618.                   }
  2619.                return typ_case(var, n->u[1].child, n->u[2].child, rt_walk,
  2620.                   maybe_var, indent);
  2621.                }
  2622.             case Cnv:
  2623.                /*
  2624.                 * RTL code: cnv: <type> ( <source> )
  2625.                 *           cnv: <type> ( <source> , <destination> )
  2626.                 */
  2627.                cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, NULL,
  2628.                   n->u[2].child, indent);
  2629.                return 1;
  2630.             case Arith_case: {
  2631.                /*
  2632.                 * arith_case (<variable>, <variable>) of {
  2633.                 *   C_integer: <statement>
  2634.                 *   integer: <statement>
  2635.                 *   C_double: <statement>
  2636.                 *   }
  2637.                 *
  2638.                 * This construct does type conversions and provides
  2639.                 *  alternate execution paths. It is necessary to keep
  2640.                 *  track of parameter locations.
  2641.                 */
  2642.                struct parminfo *strt_prms;
  2643.                struct parminfo *end_prms;
  2644.                struct parminfo *tmp_prms;
  2645.  
  2646.                strt_prms = new_prmloc();
  2647.                sv_prmloc(strt_prms);
  2648.                end_prms = new_prmloc();
  2649.                tmp_prms = new_prmloc();
  2650.  
  2651.                fall_thru = 0;
  2652.  
  2653.                n1 = n->u[2].child;   /* contains actions for the 3 cases */
  2654.  
  2655.                /*
  2656.                 * Set up an error number node for use in runerr().
  2657.                 */
  2658.                t1 = copy_t(t);
  2659.                t1->tok_id = IntConst;
  2660.                t1->image = "102";
  2661.                errnum = node0(PrimryNd, t1);
  2662.  
  2663.                /*
  2664.                 * Try converting both arguments to a C_integer.
  2665.                 */
  2666.                tok_line(t, indent);
  2667.                prt_str("if (", indent);
  2668.                cnv_fnc(t, TypECInt, n->u[0].child, NULL, NULL, indent);
  2669.                prt_str(" && ", indent);
  2670.                cnv_fnc(t, TypECInt, n->u[1].child, NULL, NULL, indent);
  2671.                prt_str(") ", indent);
  2672.                ForceNl();
  2673.                if (rt_walk(n1->u[0].child, indent + IndentInc, 0)) {
  2674.                   fall_thru |= 1;
  2675.                   mrg_prmloc(end_prms);
  2676.                   }
  2677.                ForceNl();
  2678.  
  2679.                /*
  2680.                 * Try converting both arguments to an integer.
  2681.                 */
  2682.                prt_str("#ifdef LargeInts", 0);
  2683.                ForceNl();
  2684.                ld_prmloc(strt_prms);
  2685.                tok_line(t, indent);
  2686.                prt_str("else if (", indent);
  2687.                cnv_fnc(t, TypEInt, n->u[0].child, NULL, NULL, indent);
  2688.                prt_str(" && ", indent);
  2689.                cnv_fnc(t, TypEInt, n->u[1].child, NULL, NULL, indent);
  2690.                prt_str(") ", indent);
  2691.                ForceNl();
  2692.                if (rt_walk(n1->u[1].child, indent + IndentInc, 0)) {
  2693.                   fall_thru |= 1;
  2694.                   mrg_prmloc(end_prms);
  2695.                   }
  2696.                ForceNl();
  2697.                prt_str("#endif\t\t\t\t\t/* LargeInts */", 0);
  2698.                ForceNl();
  2699.  
  2700.                /*
  2701.                 * Try converting both arguments to a C_double
  2702.                 */
  2703.                ld_prmloc(strt_prms);
  2704.                prt_str("else {", indent);
  2705.                ForceNl();
  2706.                tok_line(t, indent + IndentInc);
  2707.                prt_str("if (!", indent + IndentInc);
  2708.                cnv_fnc(t, TypCDbl, n->u[0].child, NULL, NULL,
  2709.                   indent + IndentInc);
  2710.                prt_str(")", indent + IndentInc);
  2711.                ForceNl();
  2712.                sv_prmloc(tmp_prms);   /* use original parm locs for error */
  2713.                ld_prmloc(strt_prms);
  2714.                prt_runerr(t, errnum, n->u[0].child, indent + 2 * IndentInc);
  2715.                ld_prmloc(tmp_prms);
  2716.                tok_line(t, indent + IndentInc);
  2717.                prt_str("if (!", indent + IndentInc);
  2718.                cnv_fnc(t, TypCDbl, n->u[1].child, NULL, NULL,
  2719.                   indent + IndentInc);
  2720.                prt_str(") ", indent + IndentInc);
  2721.                ForceNl();
  2722.                sv_prmloc(tmp_prms);   /* use original parm locs for error */
  2723.                ld_prmloc(strt_prms);
  2724.                prt_runerr(t, errnum, n->u[1].child, indent + 2 * IndentInc);
  2725.                ld_prmloc(tmp_prms);
  2726.                if (rt_walk(n1->u[2].child, indent + IndentInc, 0)) {
  2727.                   fall_thru |= 1;
  2728.                   mrg_prmloc(end_prms);
  2729.                   }
  2730.                ForceNl();
  2731.                prt_str("}", indent + IndentInc);
  2732.                ForceNl();
  2733.  
  2734.                ld_prmloc(end_prms);
  2735.                free(strt_prms);
  2736.                free(end_prms);
  2737.                free(tmp_prms);
  2738.                free_tree(errnum);
  2739.                return fall_thru;
  2740.                }
  2741.             }
  2742.       case QuadNd:
  2743.          /*
  2744.           * RTL code: def: <type> ( <source> , <default>)
  2745.           *           def: <type> ( <source> , <default> , <destination> )
  2746.           */
  2747.          cnv_fnc(t, icn_typ(n->u[0].child), n->u[1].child, n->u[2].child,
  2748.             n->u[3].child, indent);
  2749.          return 1;
  2750.       }
  2751.    }
  2752.  
  2753. /*
  2754.  * spcl_dcls - print special declarations for tended variables, parameter
  2755.  *  conversions, and buffers.
  2756.  */
  2757. novalue spcl_dcls(op_params)
  2758. struct sym_entry *op_params; /* operation parameters or NULL */
  2759.    {
  2760.    register struct sym_entry *sym;
  2761.    struct sym_entry *sym1;
  2762.  
  2763.    /*
  2764.     * Output declarations for buffers and locations to hold conversions
  2765.     *  to C values.
  2766.     */
  2767.    spcl_start(op_params);
  2768.  
  2769.    /*
  2770.     * Determine if this operation takes a variable number of arguments.
  2771.     *  Use that information in deciding how large a tended array to
  2772.     *  declare.
  2773.     */
  2774.    varargs = (op_params != NULL && op_params->id_type & VarPrm);
  2775.    if (varargs)
  2776.       tend_ary(ntend + VArgAlwnc - 1);
  2777.    else
  2778.       tend_ary(ntend);
  2779.  
  2780.    if (varargs) {
  2781.       /*
  2782.        * This operation takes a variable number of arguments. A declaration
  2783.        *  for a tended array has been made that will usually hold them, but
  2784.        *  sometimes it is necessary to malloc() a tended array at run
  2785.        *  time. Produce code to check for this.
  2786.        */
  2787.       cur_impl->ret_flag |= DoesEFail;  /* error conversion from allocation */
  2788.       prt_str("struct tend_desc *r_tendp;", IndentInc);
  2789.       ForceNl();
  2790.       prt_str("int r_n;\n", IndentInc);
  2791.       ++line;
  2792.       ForceNl();
  2793.       prt_str("if (r_nargs <= ", IndentInc);
  2794.       fprintf(out_file, "%d)", op_params->u.param_info.param_num + VArgAlwnc);
  2795.       ForceNl();
  2796.       prt_str("r_tendp = (struct tend_desc *)&r_tend;", 2 * IndentInc);
  2797.       ForceNl();
  2798.       prt_str("else {", IndentInc);
  2799.       ForceNl();
  2800.       prt_str(
  2801.        "r_tendp = (struct tend_desc *)malloc((msize)(sizeof(struct tend_desc)",
  2802.          2 * IndentInc);
  2803.       ForceNl();
  2804.       prt_str("", 3 * IndentInc);
  2805.       fprintf(out_file, "+ (r_nargs + %d) * sizeof(struct descrip)));", 
  2806.          ntend - 2 - op_params->u.param_info.param_num);
  2807.       ForceNl();
  2808.       prt_str("if (r_tendp == NULL) {", 2 * IndentInc);
  2809.       ForceNl();
  2810.       prt_str("err_msg(305, NULL);", 3 * IndentInc);
  2811.       ForceNl();
  2812.       prt_str("return A_Resume;", 3 * IndentInc);
  2813.       ForceNl();
  2814.       prt_str("}", 3 * IndentInc);
  2815.       ForceNl();
  2816.       prt_str("}", 2 * IndentInc);
  2817.       ForceNl();
  2818.       tendstrct = "(*r_tendp)";
  2819.       }
  2820.    else
  2821.       tendstrct = "r_tend";
  2822.  
  2823.    /*
  2824.     * Produce code to initialize the tended array. These are for tended
  2825.     *  declarations and parameters.
  2826.     */
  2827.    tend_init();  /* initializations for tended declarations. */
  2828.    if (varargs) {
  2829.       /*
  2830.        * This operation takes a variable number of arguments. Produce code
  2831.        *  to dereference or copy this into its portion of the tended
  2832.        *  array.
  2833.        */
  2834.       prt_str("for (r_n = ", IndentInc);
  2835.       fprintf(out_file, "%d; r_n < r_nargs; ++r_n)",
  2836.           op_params->u.param_info.param_num);
  2837.       ForceNl();
  2838.       if (op_params->id_type & DrfPrm) {
  2839.          prt_str("deref(&r_args[r_n], &", IndentInc * 2);
  2840.          fprintf(out_file, "%s.d[r_n + %d]);", tendstrct, ntend - 1 -
  2841.             op_params->u.param_info.param_num);
  2842.          }
  2843.       else {
  2844.          prt_str(tendstrct, IndentInc * 2);
  2845.          fprintf(out_file, ".d[r_n + %d] = r_args[r_n];", ntend - 1 -
  2846.             op_params->u.param_info.param_num);
  2847.          }
  2848.       ForceNl();
  2849.       sym = op_params->u.param_info.next;
  2850.       }
  2851.    else
  2852.       sym = op_params; /* no variable part of arg list */
  2853.  
  2854.    /*
  2855.     * Go through the fixed part of the parameter list, producing code
  2856.     *  to copy/dereference parameters into the tended array.
  2857.     */
  2858.    while (sym != NULL) {
  2859.       /*
  2860.        * A there may be identifiers for dereferenced and/or undereferenced
  2861.        *  versions of a paramater. If there are both, sym1 references the
  2862.        *  second identifier.
  2863.        */
  2864.       sym1 = sym->u.param_info.next;
  2865.       if (sym1 != NULL && sym->u.param_info.param_num !=
  2866.          sym1->u.param_info.param_num)
  2867.             sym1 = NULL;    /* the next entry is not for the same parameter */
  2868.  
  2869.       /*
  2870.        * If there are not enough arguments to supply a value for this
  2871.        *  parameter, set it to the null value.
  2872.        */
  2873.       prt_str("if (", IndentInc);
  2874.       fprintf(out_file, "r_nargs > %d) {", sym->u.param_info.param_num);
  2875.       ForceNl();
  2876.       parm_tnd(sym);
  2877.       if (sym1 != NULL) {
  2878.          ForceNl();
  2879.          parm_tnd(sym1);
  2880.          }
  2881.       ForceNl();
  2882.       prt_str("} else {", IndentInc);
  2883.       ForceNl();
  2884.       prt_str(tendstrct, IndentInc * 2);
  2885.       fprintf(out_file, ".d[%d].dword = D_Null;", sym->t_indx);
  2886.       if (sym1 != NULL) {
  2887.          ForceNl();
  2888.          prt_str(tendstrct, IndentInc * 2);
  2889.          fprintf(out_file, ".d[%d].dword = D_Null;", sym1->t_indx);
  2890.          }
  2891.       ForceNl();
  2892.       prt_str("}", 2 * IndentInc);
  2893.       ForceNl();
  2894.       if (sym1 == NULL)
  2895.          sym = sym->u.param_info.next;
  2896.       else
  2897.          sym = sym1->u.param_info.next;
  2898.       }
  2899.  
  2900.    /*
  2901.     * Finish setting up the tended array structure and link it into the tended
  2902.     *  list.
  2903.     */
  2904.    if (ntend != 0) {
  2905.       prt_str(tendstrct, IndentInc);
  2906.       if (varargs)
  2907.          fprintf(out_file, ".num = %d + Max(r_nargs - %d, 0);", ntend - 1,
  2908.             op_params->u.param_info.param_num);
  2909.       else
  2910.          fprintf(out_file, ".num = %d;", ntend);
  2911.       ForceNl();
  2912.       prt_str(tendstrct, IndentInc);
  2913.       prt_str(".previous = tend;", IndentInc);
  2914.       ForceNl();
  2915.       prt_str("tend = (struct tend_desc *)&", IndentInc);
  2916.       fprintf(out_file, "%s;", tendstrct);
  2917.       ForceNl();
  2918.       }
  2919.    }
  2920.  
  2921. /*
  2922.  * spcl_start - do initial work for outputing special declarations. Output
  2923.  *  declarations for buffers and locations to hold conversions to C values.
  2924.  *  Determine what tended locations are needed for parameters.
  2925.  */
  2926. static novalue spcl_start(op_params)
  2927. struct sym_entry *op_params;
  2928.    {
  2929.    ForceNl();
  2930.    if (n_tmp_str > 0) {
  2931.       prt_str("char r_sbuf[", IndentInc);
  2932.       fprintf(out_file, "%d][MaxCvtLen];", n_tmp_str);
  2933.       ForceNl();
  2934.       }
  2935.    if (n_tmp_cset > 0) {
  2936.       prt_str("struct b_cset r_cbuf[", IndentInc);
  2937.       fprintf(out_file, "%d];", n_tmp_cset);
  2938.       ForceNl();
  2939.       }
  2940.    if (tend_lst == NULL)
  2941.       ntend = 0;
  2942.    else
  2943.       ntend = tend_lst->t_indx + 1;
  2944.    parm_locs(op_params); /* see what parameter conversion there are */
  2945.    }
  2946.  
  2947. /*
  2948.  * tend_ary - write struct containing array of tended descriptors.
  2949.  */
  2950. static novalue tend_ary(n)
  2951. int n;
  2952.    {
  2953.    if (n == 0)
  2954.       return;
  2955.    prt_str("struct {", IndentInc);
  2956.    ForceNl();
  2957.    prt_str("struct tend_desc *previous;", 2 * IndentInc);
  2958.    ForceNl();
  2959.    prt_str("int num;", 2 * IndentInc);
  2960.    ForceNl();
  2961.    prt_str("struct descrip d[", 2 * IndentInc);
  2962.    fprintf(out_file, "%d];", n);
  2963.    ForceNl();
  2964.    prt_str("} r_tend;\n", 2 * IndentInc);
  2965.    ++line;
  2966.    ForceNl();
  2967.    }
  2968.  
  2969. /*
  2970.  * tend_init - produce code to initialize entries in the tended array
  2971.  *  corresponding to tended declarations. Default initializations are
  2972.  *  supplied when there is none in the declaration.
  2973.  */
  2974. static novalue tend_init()
  2975.    {
  2976.    register struct init_tend *tnd;
  2977.  
  2978.    for (tnd = tend_lst; tnd != NULL; tnd = tnd->next) {
  2979.       switch (tnd->init_typ) {
  2980.          case TndDesc:
  2981.             /*
  2982.              * Simple tended declaration.
  2983.              */
  2984.             prt_str(tendstrct, IndentInc);
  2985.             if (tnd->init == NULL)
  2986.                fprintf(out_file, ".d[%d].dword = D_Null;", tnd->t_indx);
  2987.             else {
  2988.                fprintf(out_file, ".d[%d] = ", tnd->t_indx);
  2989.                c_walk(tnd->init, 2 * IndentInc, 0);
  2990.                prt_str(";", 2 * IndentInc);
  2991.                }
  2992.             break;
  2993.          case TndStr:
  2994.             /*
  2995.              * Tended character pointer.
  2996.              */
  2997.             prt_str(tendstrct, IndentInc);
  2998.             if (tnd->init == NULL)
  2999.                fprintf(out_file, ".d[%d] = emptystr;", tnd->t_indx);
  3000.             else {
  3001.                fprintf(out_file, ".d[%d].dword = 0;", tnd->t_indx);
  3002.                ForceNl();
  3003.                prt_str(tendstrct, IndentInc);
  3004.                fprintf(out_file, ".d[%d].vword.sptr = ", tnd->t_indx);
  3005.                c_walk(tnd->init, 2 * IndentInc, 0);
  3006.                prt_str(";", 2 * IndentInc);
  3007.                }
  3008.             break;
  3009.          case TndBlk:
  3010.             /*
  3011.              * A tended block pointer of some kind.
  3012.              */
  3013.             prt_str(tendstrct, IndentInc);
  3014.             if (tnd->init == NULL)
  3015.                fprintf(out_file, ".d[%d] = nullptr;", tnd->t_indx);
  3016.             else {
  3017.                fprintf(out_file, ".d[%d].dword = F_Ptr | F_Nqual;",tnd->t_indx);
  3018.                ForceNl();
  3019.                prt_str(tendstrct, IndentInc);
  3020.                fprintf(out_file, ".d[%d].vword.bptr = (union block *)",
  3021.                    tnd->t_indx);
  3022.                c_walk(tnd->init, 2 * IndentInc, 0);
  3023.                prt_str(";", 2 * IndentInc);
  3024.                }
  3025.             break;
  3026.          }
  3027.       ForceNl();
  3028.       }
  3029.    }
  3030.  
  3031. /*
  3032.  * parm_tnd - produce code to put a parameter in its tended location.
  3033.  */
  3034. static novalue parm_tnd(sym)
  3035. struct sym_entry *sym;
  3036.    {
  3037.    /*
  3038.     * A parameter may either be dereferenced into its tended location
  3039.     *  or copied.
  3040.     */
  3041.    if (sym->id_type & DrfPrm) {
  3042.       prt_str("deref(&r_args[", IndentInc * 2);
  3043.       fprintf(out_file, "%d], &%s.d[%d]);", sym->u.param_info.param_num,
  3044.          tendstrct, sym->t_indx);
  3045.       }
  3046.    else {
  3047.       prt_str(tendstrct, IndentInc * 2);
  3048.       fprintf(out_file, ".d[%d] = r_args[%d];", sym->t_indx,
  3049.          sym->u.param_info.param_num);
  3050.       }
  3051.    }
  3052.  
  3053. /*
  3054.  * parm_locs - determine what locations are needed to hold parameters and
  3055.  *  their conversions. Produce declarations for the C_integer and C_double
  3056.  *  locations.
  3057.  */
  3058. static novalue parm_locs(op_params)
  3059. struct sym_entry *op_params;
  3060.    {
  3061.    struct sym_entry *next_parm;
  3062.  
  3063.    /*
  3064.     * Parameters are stored in reverse order: Recurse down the list
  3065.     *  and perform processing on the way back.
  3066.     */
  3067.    if (op_params == NULL)
  3068.       return;
  3069.    next_parm = op_params->u.param_info.next;
  3070.    parm_locs(next_parm);
  3071.  
  3072.    /*
  3073.     * For interpreter routines, extra tended descriptors are only needed
  3074.     *  when both dereferenced and undereferenced values are requested.
  3075.     */
  3076.    if (iconx_flg && (next_parm == NULL ||
  3077.       op_params->u.param_info.param_num != next_parm->u.param_info.param_num))
  3078.       op_params->t_indx = -1;
  3079.    else
  3080.       op_params->t_indx = ntend++;
  3081.    if (op_params->u.param_info.non_tend & PrmInt) {
  3082.       prt_str("C_integer r_i", IndentInc);
  3083.       fprintf(out_file, "%d;", op_params->u.param_info.param_num);
  3084.       ForceNl();
  3085.       }
  3086.    if (op_params->u.param_info.non_tend & PrmDbl) {
  3087.       prt_str("double r_d", IndentInc);
  3088.       fprintf(out_file, "%d;", op_params->u.param_info.param_num);
  3089.       ForceNl();
  3090.       }
  3091.    }
  3092.  
  3093. /*
  3094.  * real_def - see if a declaration really defines storage.
  3095.  */
  3096. static int real_def(n)
  3097. struct node *n;
  3098.    {
  3099.    struct node *dcl_lst;
  3100.  
  3101.    dcl_lst = n->u[1].child;
  3102.    /*
  3103.     * If no variables are being defined this must be a tag declaration.
  3104.     */
  3105.    if (dcl_lst == NULL)
  3106.       return 0;
  3107.    
  3108.    if (only_proto(dcl_lst))
  3109.       return 0;
  3110.  
  3111.    if (tdef_or_extr(n->u[0].child))
  3112.       return 0;
  3113.  
  3114.    return 1;
  3115.    }
  3116.  
  3117. /*
  3118.  * only_proto - see if this declarator list contains only function prototypes.
  3119.  */
  3120. static int only_proto(n)
  3121. struct node *n;
  3122.    {
  3123.    switch (n->nd_id) {
  3124.       case CommaNd:
  3125.          return only_proto(n->u[0].child) & only_proto(n->u[1].child);
  3126.       case ConCatNd:
  3127.          /*
  3128.           * Optional pointer.
  3129.           */
  3130.          return only_proto(n->u[1].child);
  3131.       case BinryNd:
  3132.          switch (n->tok->tok_id) {
  3133.             case '=':
  3134.                return only_proto(n->u[0].child);
  3135.             case '[':
  3136.                /*
  3137.                 * At this point, assume array declarator is not part of
  3138.                 *  prototype.
  3139.                 */
  3140.                return 0;
  3141.             case ')':
  3142.                /*
  3143.                 * Prototype (or forward declaration).
  3144.                 */
  3145.                return 1;
  3146.             }
  3147.       case PrefxNd:
  3148.          /*
  3149.           * Parenthesized.
  3150.           */
  3151.          return only_proto(n->u[0].child);
  3152.       case PrimryNd:
  3153.          /*
  3154.           * At this point, assume it is not a prototype.
  3155.           */
  3156.          return 0;
  3157.       }
  3158.    err1("rtt internal error detected in function only_proto()");
  3159.    /* NOTREACHED */
  3160.    }
  3161.  
  3162. /*
  3163.  * tdef_or_extr - see if this is a typedef or extern.
  3164.  */
  3165. static int tdef_or_extr(n)
  3166. struct node *n;
  3167.    {
  3168.    switch (n->nd_id) {
  3169.       case LstNd:
  3170.          return tdef_or_extr(n->u[0].child) | tdef_or_extr(n->u[1].child);
  3171.       case BinryNd:
  3172.          /*
  3173.           * struct, union, or enum.
  3174.           */
  3175.          return 0;
  3176.       case PrimryNd:
  3177.          if (n->tok->tok_id == Extern || n->tok->tok_id == Typedef)
  3178.             return 1;
  3179.          else
  3180.             return 0;
  3181.       }
  3182.    err1("rtt internal error detected in function tdef_or_extr()");
  3183.    /* NOTREACHED */
  3184.    }
  3185.  
  3186. /*
  3187.  * dclout - output an ordinary global C declaration.
  3188.  */
  3189. novalue dclout(n)
  3190. struct node *n;
  3191.    {
  3192.    if (!enable_out)
  3193.       return;        /* output disabled */
  3194.    if (real_def(n))
  3195.       def_fnd = 1;   /* this declaration defines a run-time object */
  3196.    c_walk(n, 0, 0);
  3197.    free_tree(n);
  3198.    }
  3199.  
  3200. /*
  3201.  * fncout - output code for a C function.
  3202.  */
  3203. novalue fncout(head, prm_dcl, block)
  3204. struct node *head;
  3205. struct node *prm_dcl;
  3206. struct node *block;
  3207.    {
  3208.    if (!enable_out)
  3209.       return;       /* output disabled */
  3210.  
  3211.    def_fnd = 1;     /* this declaration defines a run-time object */
  3212.  
  3213.    nxt_sbuf = 0;    /* clear number of string buffers */
  3214.    nxt_cbuf = 0;    /* clear number of cset buffers */
  3215.  
  3216.    /*
  3217.     * Output the function header and the parameter declarations.
  3218.     */
  3219.    fnc_head = head;
  3220.    c_walk(head, 0, 0);
  3221.    prt_str(" ",  0);
  3222.    c_walk(prm_dcl, 0, 0);
  3223.    prt_str(" ", 0);
  3224.  
  3225.    /* 
  3226.     * Handle outer block.
  3227.     */
  3228.    prt_tok(block->tok, IndentInc);          /* { */
  3229.    c_walk(block->u[0].child, IndentInc, 0); /* non-tended declarations */
  3230.    spcl_dcls(NULL);                         /* tended declarations */
  3231.    no_ret_val = 1;
  3232.    c_walk(block->u[2].child, IndentInc, 0); /* statement list */
  3233.    if (ntend != 0 && no_ret_val) {
  3234.       /*
  3235.        * This function contains no return statements with values, assume
  3236.        *  that the programmer is using the implicit return at the end
  3237.        *  of the function and update the tending of descriptors.
  3238.        */
  3239.       untend(IndentInc);
  3240.       }
  3241.    ForceNl();
  3242.    prt_str("}", IndentInc);
  3243.    ForceNl();
  3244.  
  3245.    /*
  3246.     * free storage.
  3247.     */
  3248.    free_tree(head);
  3249.    free_tree(prm_dcl);
  3250.    free_tree(block);
  3251.    pop_cntxt();
  3252.    clr_def();
  3253.    }
  3254.  
  3255. /*
  3256.  * defout - output operation definitions (except for constant keywords)
  3257.  */
  3258. novalue defout(n)
  3259. struct node *n;
  3260.    {
  3261.    struct sym_entry *sym, *sym1;
  3262.  
  3263.    if (!enable_out)
  3264.       return;       /* output disabled */
  3265.  
  3266.    nxt_sbuf = 0;
  3267.    nxt_cbuf = 0;
  3268.  
  3269.    /*
  3270.     * Somewhat different code is produced for the interpreter and compiler.
  3271.     */
  3272.    if (iconx_flg)
  3273.       interp_def(n);
  3274.    else
  3275.       comp_def(n);
  3276.  
  3277.    free_tree(n);
  3278.    /*
  3279.     * The declarations for the declare statement are not associated with
  3280.     *  any compound statement and must be freed here.
  3281.     */
  3282.    sym = dcl_stk->tended;
  3283.    while (sym != NULL) {
  3284.       sym1 = sym;
  3285.       sym = sym->u.tnd_var.next;
  3286.       free_sym(sym1);
  3287.       }
  3288.    while (decl_lst != NULL) {
  3289.       sym1 = decl_lst;
  3290.       decl_lst = decl_lst->u.declare_var.next;
  3291.       free_sym(sym1);
  3292.       }
  3293.    op_type = OrdFunc;
  3294.    pop_cntxt();
  3295.    clr_def();
  3296.    }
  3297.  
  3298. /*
  3299.  * comp_def - output code for the compiler for operation definitions.
  3300.  */
  3301. static novalue comp_def(n)
  3302. struct node *n;
  3303.    {
  3304. #ifdef Rttx
  3305.    fprintf(stdout, "rtt was compiled to only support the interpreter, use -x\n");
  3306.    exit(ErrorExit);
  3307. #else                    /* Rttx */
  3308.    struct sym_entry *sym;
  3309.    struct node *n1;
  3310.    FILE *f_save;
  3311.    char buf1[5];
  3312.    char buf[MaxFileName];
  3313.    char *cname;
  3314.    long min_result;
  3315.    long max_result;
  3316.    int ret_flag;
  3317.    int resume;
  3318.    char *name;
  3319.    char *s;
  3320.  
  3321.    f_save = out_file;
  3322.  
  3323.    /*
  3324.     * Note if the result location is explicitly referenced and note
  3325.     *  how it is accessed in the generated code.
  3326.     */
  3327.    cur_impl->use_rslt = sym_lkup(str_rslt)->u.referenced;
  3328.    rslt_loc = "(*r_rslt)";
  3329.  
  3330.    /*
  3331.     * In several contexts, letters are used to distinguish kinds of operations.
  3332.     */
  3333.    switch (op_type) {
  3334.       case Function:
  3335.          lc_letter = 'f';
  3336.          uc_letter = 'F';
  3337.          break;
  3338.       case Keyword:
  3339.          lc_letter = 'k';
  3340.          uc_letter = 'K';
  3341.          break;
  3342.       case Operator:
  3343.          lc_letter = 'o';
  3344.          uc_letter = 'O';
  3345.       }
  3346.    prfx1 = cur_impl->prefix[0];
  3347.    prfx2 = cur_impl->prefix[1];
  3348.  
  3349.    if (op_type != Keyword) {
  3350.       /*
  3351.        * First pass through the operation: produce most general routine.
  3352.        */
  3353.       fnc_ret = RetSig;  /* most general routine always returns a signal */
  3354.  
  3355.       /*
  3356.        * Compute the file name in which to output the function.
  3357.        */
  3358.       sprintf(buf1, "%c_%c%c", lc_letter, prfx1, prfx2);
  3359.       cname = salloc(makename(buf, SourceDir, buf1, CSuffix));
  3360.       if ((out_file = fopen(cname, "w")) == NULL)
  3361.          err2("cannot open output file", cname);
  3362.       else
  3363.          addrmlst(cname);
  3364.          
  3365.       prologue(); /* output standard comments and preprocessor directives */
  3366.  
  3367.       /*
  3368.        * Output function header that corresponds to standard calling
  3369.        *  convensions. The function name is constructed from the letter
  3370.        *  for the operation type, the prefix that makes the function
  3371.        *  name unique, and the name of the operation.
  3372.        */
  3373.       fprintf(out_file, "int %c%c%c_%s(r_nargs, r_args, r_rslt, r_s_cont)\n",
  3374.          uc_letter, prfx1, prfx2, cur_impl->name);
  3375.       fprintf(out_file, "int r_nargs;\n");
  3376.       fprintf(out_file, "dptr r_args;\n");
  3377.       fprintf(out_file, "dptr r_rslt;\n");
  3378.       fprintf(out_file, "continuation r_s_cont;");
  3379.       fname = cname;
  3380.       line = 12;
  3381.       ForceNl();
  3382.       prt_str("{", IndentInc);
  3383.       ForceNl();
  3384.  
  3385.       /*
  3386.        * Output ordinary declarations from declare clause.
  3387.        */
  3388.       for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
  3389.          c_walk(sym->u.declare_var.tqual, IndentInc, 0);
  3390.          prt_str(" ", IndentInc);
  3391.          c_walk(sym->u.declare_var.dcltor, IndentInc, 0);
  3392.          if ((n1 = sym->u.declare_var.init) != NULL) {
  3393.             prt_str(" = ", IndentInc);
  3394.             c_walk(n1, IndentInc, 0);
  3395.             }
  3396.          prt_str(";", IndentInc);
  3397.          }
  3398.  
  3399.       /*
  3400.        * Output code for special declarations along with code to initial
  3401.        *  them. This includes buffers and tended locations for parameters
  3402.        *  and tended variables.
  3403.        */
  3404.       spcl_dcls(params);
  3405.  
  3406.       if (rt_walk(n, IndentInc, 0)) {  /* body of operation */
  3407.          if (n->nd_id == ConCatNd)
  3408.             s = n->u[1].child->tok->fname;
  3409.          else
  3410.             s = n->tok->fname;
  3411.          fprintf(stderr, "%s: file %s, warning: ", progname, s);
  3412.          fprintf(stderr, "execution may fall off end of operation \"%s\"\n",
  3413.              cur_impl->name);
  3414.          }
  3415.  
  3416.       ForceNl();
  3417.       prt_str("}\n", IndentInc);
  3418.       if (fclose(out_file) != 0)
  3419.          err2("cannot close ", cname);
  3420.       put_c_fl(cname, 1);  /* note name of output file for operation */
  3421.       }
  3422.  
  3423.    /*
  3424.     * Second pass through operation: produce in-line code and special purpose
  3425.     *  routines.
  3426.     */
  3427.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  3428.       if (sym->id_type & DrfPrm)
  3429.          sym->u.param_info.cur_loc = PrmTend;  /* reset location of parameter */
  3430.    in_line(n);
  3431.  
  3432.    /*
  3433.     * Insure that the fail/return/suspend statements are consistent
  3434.     *  with the result sequence indicated.
  3435.     */
  3436.    min_result = cur_impl->min_result;
  3437.    max_result = cur_impl->max_result;
  3438.    ret_flag = cur_impl->ret_flag;
  3439.    resume = cur_impl->resume;
  3440.    name = cur_impl->name;
  3441.    if (min_result == NoRsltSeq && ret_flag & (DoesFail|DoesRet|DoesSusp))
  3442.       err2(name,
  3443.          ": result sequence of {}, but fail, return, or suspend present");
  3444.    if (min_result != NoRsltSeq && ret_flag == 0)
  3445.       err2(name,
  3446.          ": result sequence indicated, no fail, return, or suspend present");
  3447.    if (max_result != NoRsltSeq) {
  3448.       if (max_result == 0 && ret_flag & (DoesRet|DoesSusp))
  3449.          err2(name,
  3450.             ": result sequence of 0 length, but return or suspend present");
  3451.       if (max_result != 0 && !(ret_flag & (DoesRet | DoesSusp)))
  3452.          err2(name,
  3453.             ": result sequence length > 0, but no return or suspend present");
  3454.       if ((max_result == UnbndSeq || max_result > 1 || resume) &&
  3455.          !(ret_flag & DoesSusp))
  3456.          err2(name,
  3457.             ": result sequence indicates suspension, but no suspend present");
  3458.       if ((max_result != UnbndSeq && max_result <= 1 && !resume) &&
  3459.          ret_flag & DoesSusp)
  3460.          err2(name,
  3461.             ": result sequence indicates no suspension, but suspend present");
  3462.       }
  3463.    if (min_result != NoRsltSeq && max_result != UnbndSeq &&
  3464.       min_result > max_result)
  3465.       err2(name, ": minimum result sequence length greater than maximum");
  3466.  
  3467.    out_file = f_save;
  3468. #endif                    /* Rttx */
  3469.    }
  3470.  
  3471. /*
  3472.  * interp_def - output code for the interpreter for operation definitions.
  3473.  */
  3474. static novalue interp_def(n)
  3475. struct node *n;
  3476.    {
  3477.    struct sym_entry *sym;
  3478.    struct node *n1;
  3479.    int nparms;
  3480.    int has_underef;
  3481.    char letter;
  3482.    char *name;
  3483.    char *s;
  3484.  
  3485.    /*
  3486.     * Note how result location is accessed in generated code.
  3487.     */
  3488.    rslt_loc = "r_args[0]";
  3489.  
  3490.    /*
  3491.     * Determine if the operation has any undereferenced parameters.
  3492.     */
  3493.    has_underef = 0;
  3494.    for (sym = params; sym != NULL; sym = sym->u.param_info.next)
  3495.       if (sym->id_type  & RtParm) {
  3496.          has_underef = 1;
  3497.          break;
  3498.          }
  3499.  
  3500.    /*
  3501.     * Determine the nuber of parameters. A negative value is used
  3502.     *  to indicate an operation that takes a variable number of
  3503.     *  arguments.
  3504.     */
  3505.    if (params == NULL)
  3506.       nparms = 0;
  3507.    else {
  3508.       nparms = params->u.param_info.param_num + 1;
  3509.       if (params->id_type & VarPrm)
  3510.          nparms = -nparms;
  3511.       }
  3512.  
  3513.    fnc_ret = RetSig;  /* interpreter routine always returns a signal */
  3514.    name = cur_impl->name;
  3515.  
  3516.    /*
  3517.     * Determine what letter is used to prefix the operation name.
  3518.     */
  3519.    switch (op_type) {
  3520.       case Function:
  3521.  
  3522. #if VMS
  3523.          letter = 'Y';
  3524. #else                    /* VMS */
  3525.          letter = 'X';
  3526. #endif                    /* VMS */
  3527.  
  3528.          break;
  3529.       case Keyword:
  3530.          letter = 'K';
  3531.          break;
  3532.       case Operator:
  3533.          letter = 'O';
  3534.          }
  3535.  
  3536.    fprintf(out_file, "\n");
  3537.    if (op_type != Keyword) {
  3538.       /*
  3539.        * Output prototype. Operations taking a variable number of arguments
  3540.        *   have an extra parameter: the number of arguments.
  3541.        */
  3542.       fprintf(out_file, "int %c%s Params((", letter, name);
  3543.       if (params != NULL && (params->id_type & VarPrm))
  3544.          fprintf(out_file, "int r_nargs, ");
  3545.       fprintf(out_file, "dptr r_args));\n");
  3546.       ++line;
  3547.  
  3548.       /*
  3549.        * Output procedure block.
  3550.        */
  3551.       switch (op_type) {
  3552.          case Function:
  3553.             fprintf(out_file, "FncBlock(%s, %d, %d)\n\n", name, nparms, 
  3554.                (has_underef ? -1 : 0));
  3555.             ++line;
  3556.             break;
  3557.          case Operator:
  3558.             if (strcmp(cur_impl->op,"\\") == 0)
  3559.                fprintf(out_file, "OpBlock(%s, %d, \"%s\", 0)\n\n", name, nparms,
  3560.                   "\\\\");
  3561.             else
  3562.                fprintf(out_file, "OpBlock(%s, %d, \"%s\", 0)\n\n", name, nparms,
  3563.                   cur_impl->op);
  3564.             ++line;
  3565.          }
  3566.       }
  3567.  
  3568.    /*
  3569.     * Output function header. Operations taking a variable number of arguments
  3570.     *   have an extra parameter: the number of arguments.
  3571.     */
  3572.    fprintf(out_file, "int %c%s(", letter, name);
  3573.    if (params != NULL && (params->id_type & VarPrm))
  3574.       fprintf(out_file, "r_nargs, ");
  3575.    fprintf(out_file, "r_args)\n");
  3576.    ++line;
  3577.    if (params != NULL && (params->id_type & VarPrm)) {
  3578.       fprintf(out_file, "int r_nargs;\n");
  3579.       ++line;
  3580.       }
  3581.    fprintf(out_file, "dptr r_args;");
  3582.    ++line;
  3583.    ForceNl();
  3584.    prt_str("{", IndentInc);
  3585.       
  3586.    /*
  3587.     * Output ordinary declarations from the declare clause.
  3588.     */
  3589.    ForceNl();
  3590.    for (sym = decl_lst; sym != NULL; sym = sym->u.declare_var.next) {
  3591.       c_walk(sym->u.declare_var.tqual, IndentInc, 0);
  3592.       prt_str(" ", IndentInc);
  3593.       c_walk(sym->u.declare_var.dcltor, IndentInc, 0);
  3594.       if ((n1 = sym->u.declare_var.init) != NULL) {
  3595.          prt_str(" = ", IndentInc);
  3596.          c_walk(n1, IndentInc, 0);
  3597.          }
  3598.       prt_str(";", IndentInc);
  3599.       }
  3600.  
  3601.    /*
  3602.     * Output special declarations and initial processing.
  3603.     */
  3604.    tendstrct = "r_tend";
  3605.    spcl_start(params);
  3606.    tend_ary(ntend);
  3607.    if (has_underef && params != NULL && params->id_type == (VarPrm | DrfPrm))
  3608.       prt_str("int r_n;\n", IndentInc);
  3609.    tend_init();
  3610.  
  3611.    /*
  3612.     * See which parameters need to be dereferenced. If all are dereferenced,
  3613.     *  it is done by before the routine is called.
  3614.     */
  3615.    if (has_underef) {
  3616.       sym = params;
  3617.       if (sym != NULL && sym->id_type & VarPrm) {
  3618.          if (sym->id_type & DrfPrm) {
  3619.             /*
  3620.              * There is a variable part of the parameter list and it
  3621.              *  must be dereferenced.
  3622.              */
  3623.             prt_str("for (r_n = ", IndentInc);
  3624.             fprintf(out_file, "%d; r_n <= r_nargs; ++r_n)",
  3625.                 sym->u.param_info.param_num + 1);
  3626.             ForceNl();
  3627.             prt_str("Deref(r_args[r_n]);", IndentInc * 2);
  3628.             ForceNl();
  3629.             }
  3630.          sym = sym->u.param_info.next;
  3631.          }
  3632.  
  3633.       /*
  3634.        * Produce code to dereference any fixed parameters that need to be.
  3635.        */
  3636.       while (sym != NULL) {
  3637.          if (sym->id_type & DrfPrm) {
  3638.             /*
  3639.              * Tended index of -1 indicates that the parameter can be
  3640.              *  dereferened in-place (this is the usual case).
  3641.              */
  3642.             if (sym->t_indx == -1) {
  3643.                prt_str("Deref(r_args[", IndentInc * 2);
  3644.                fprintf(out_file, "%d]);", sym->u.param_info.param_num + 1);
  3645.                }
  3646.             else {
  3647.                prt_str("deref(&r_args[", IndentInc * 2);
  3648.                fprintf(out_file, "%d], &r_tend.d[%d]);",
  3649.                   sym->u.param_info.param_num + 1, sym->t_indx);
  3650.                }
  3651.             }
  3652.          ForceNl();
  3653.          sym = sym->u.param_info.next;
  3654.          }
  3655.       }
  3656.  
  3657.    /*
  3658.     * Finish setting up the tended array structure and link it into the tended
  3659.     *  list.
  3660.     */
  3661.    if (ntend != 0) {
  3662.       prt_str("r_tend.num = ", IndentInc);
  3663.       fprintf(out_file, "%d;", ntend);
  3664.       ForceNl();
  3665.       prt_str("r_tend.previous = tend;", IndentInc);
  3666.       ForceNl();
  3667.       prt_str("tend = (struct tend_desc *)&r_tend;", IndentInc);
  3668.       ForceNl();
  3669.       }
  3670.  
  3671.    if (rt_walk(n, IndentInc, 0)) { /* body of operation */
  3672.       if (n->nd_id == ConCatNd)
  3673.          s = n->u[1].child->tok->fname;
  3674.       else
  3675.          s = n->tok->fname;
  3676.       fprintf(stderr, "%s: file %s, warning: ", progname, s);
  3677.       fprintf(stderr, "execution may fall off end of operation \"%s\"\n",
  3678.           cur_impl->name);
  3679.       }
  3680.    ForceNl();
  3681.    prt_str("}\n", IndentInc);
  3682.    }
  3683.  
  3684. /*
  3685.  * keyconst - produce code for a constant keyword.
  3686.  */
  3687. novalue keyconst(t)
  3688. struct token *t;
  3689.    {
  3690.    struct il_code *il;
  3691.    int n;
  3692.  
  3693.    if (iconx_flg) {
  3694.       /*
  3695.        * For the interpreter, output a C function implementing the keyword.
  3696.        */
  3697.       rslt_loc = "r_args[0]";  /* result location */
  3698.  
  3699.       fprintf(out_file, "\n");
  3700.       fprintf(out_file, "int K%s(r_args)\n", cur_impl->name);
  3701.       fprintf(out_file, "dptr r_args;");
  3702.       line += 2;
  3703.       ForceNl();
  3704.       prt_str("{", IndentInc);
  3705.       ForceNl();
  3706.       switch (t->tok_id) {
  3707.          case StrLit:
  3708.             prt_str(rslt_loc, IndentInc);
  3709.             prt_str(".vword.sptr = \"", IndentInc);
  3710.             n = prt_i_str(out_file, t->image, (int)strlen(t->image));
  3711.             prt_str("\";", IndentInc);
  3712.             ForceNl();
  3713.             prt_str(rslt_loc, IndentInc);
  3714.             fprintf(out_file, ".dword = %d;", n);
  3715.             break;
  3716.          case CharConst:
  3717.             prt_str("static struct b_cset cset_blk = ", IndentInc);
  3718.             cset_init(out_file, bitvect(t->image, (int)strlen(t->image)));
  3719.             ForceNl();
  3720.             prt_str(rslt_loc, IndentInc);
  3721.             prt_str(".dword = D_Cset;", IndentInc);
  3722.             ForceNl();
  3723.             prt_str(rslt_loc, IndentInc);
  3724.             prt_str(".vword.bptr = (union block *)&cset_blk;", IndentInc);
  3725.             break;
  3726.          case DblConst:
  3727.             prt_str("static struct b_real real_blk = {T_Real, ", IndentInc);
  3728.             fprintf(out_file, "%s};", t->image);
  3729.             ForceNl();
  3730.             prt_str(rslt_loc, IndentInc);
  3731.             prt_str(".dword = D_Real;", IndentInc);
  3732.             ForceNl();
  3733.             prt_str(rslt_loc, IndentInc);
  3734.             prt_str(".vword.bptr = (union block *)&real_blk;", IndentInc);
  3735.             break;
  3736.          case IntConst:
  3737.             prt_str(rslt_loc, IndentInc);
  3738.             prt_str(".dword = D_Integer;", IndentInc);
  3739.             ForceNl();
  3740.             prt_str(rslt_loc, IndentInc);
  3741.             prt_str(".vword.integr = ", IndentInc);
  3742.             prt_str(t->image, IndentInc);
  3743.             prt_str(";", IndentInc);
  3744.             break;
  3745.          }
  3746.       ForceNl();
  3747.       prt_str("return A_Continue;", IndentInc);
  3748.       ForceNl();
  3749.       prt_str("}\n", IndentInc);
  3750.       ++line;
  3751.       ForceNl();
  3752.       }
  3753.    else {
  3754.       /*
  3755.        * For the compiler, make an entry in the data base for the keyword.
  3756.        */
  3757.       cur_impl->use_rslt = 0;
  3758.    
  3759.       il = new_il(IL_Const, 2);
  3760.       switch (t->tok_id) {
  3761.          case StrLit:
  3762.             il->u[0].n = str_typ;
  3763.             il->u[1].s = (char *)alloc((unsigned int)(strlen(t->image) + 3));
  3764.             sprintf(il->u[1].s, "\"%s\"", t->image);
  3765.             break;
  3766.          case CharConst:
  3767.             il->u[0].n = cset_typ;
  3768.             il->u[1].s = (char *)alloc((unsigned int)(strlen(t->image) + 3));
  3769.             sprintf(il->u[1].s, "'%s'", t->image);
  3770.             break;
  3771.          case DblConst:
  3772.             il->u[0].n = real_typ;
  3773.             il->u[1].s = t->image;
  3774.             break;
  3775.          case IntConst:
  3776.             il->u[0].n = int_typ;
  3777.             il->u[1].s = t->image;
  3778.             break;
  3779.          }
  3780.       cur_impl->in_line = il;
  3781.       }
  3782.  
  3783.    /*
  3784.     * Reset the translator and free storage.
  3785.     */
  3786.    op_type = OrdFunc;
  3787.    free_t(t);
  3788.    pop_cntxt();
  3789.    clr_def();
  3790.    }
  3791.  
  3792. /*
  3793.  * keepdir - A preprocessor directive to be kept has been encountered.
  3794.  *   If it is #passthru, print just the body of the directive, otherwise
  3795.  *   print the whole thing.
  3796.  */
  3797. novalue keepdir(t)
  3798. struct token *t;
  3799.    {
  3800.    char *s;
  3801.  
  3802.    tok_line(t, 0);
  3803.    s = t->image;
  3804.    if (strncmp(s, "#passthru", 9) == 0)
  3805.       s = s + 10;
  3806.    fprintf(out_file, "%s\n", s);
  3807.    line += 1;
  3808.    }
  3809.  
  3810. /*
  3811.  * prologue - print standard comments and preprocessor directives at the
  3812.  *   start of an output file.
  3813.  */
  3814. novalue prologue()
  3815.    {
  3816.    id_comment(out_file);
  3817.    fprintf(out_file, "%s", compiler_def);
  3818.    fprintf(out_file, "#include \"%s\"\n\n", inclname);
  3819.    }
  3820.