home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 355_02 / slk2.exe / SPP / SEM.C < prev    next >
C/C++ Source or Header  |  1991-06-09  |  28KB  |  1,333 lines

  1. /*
  2.     New Sherlock preprocessor -- semantic routines.
  3.  
  4.     Source: sem.c
  5.     Started: October 1, 1987
  6.     Version:
  7.         June 9, 1991:  bug fixes originally made by Roberto Artigas
  8.             These fixes were made in 1990.
  9.         July 15, 1988
  10.         February 2, 1989: bug fixes:
  11.             is_base()    make STRING_TOK a valid base type.
  12.             sd_htype()    convert to string, unsigned_long.
  13.             out_type()    add %u and %lu printf types.
  14.             so_2exit()    call r_uint to print unsigned.
  15.             so_usr()    call sl_uint to print unsigned.
  16.         February 14, 1989: bug fixes:
  17.             sd_htype(), sd_type() call new new_type() routine.
  18.             sd_end()    reset cur_hptype, cur_hftype.
  19.             This makes unsigned int, unsigned short always work.
  20.             so_usr()    decrease output lines and call
  21.                     sl_csout(), sl_lpout(), sl_rpout().
  22.             sd_func()    add error message.
  23.         February 15, 1989: changes:
  24.             so_printf()    only 5 printf specs per line.
  25.         February 15, 1989: changes:
  26.             fn_enable, fn_gen, fn_warn flags added.
  27.             fn_name made global.
  28.         February 25, 1989: bug fix to so_disable.
  29.         February 27, 1989: support for sl_sbout().
  30.         March 1, 1989:  better versions of so_printf() and so_usr().
  31.         March 5, 1989:  bug fix in so_entry().
  32.     Version 1.4:        
  33.         June 27, 1989:
  34.             o bug fix in so_2exit() so structs/unions generate
  35.             TICKX's on exit instead of RETURN_PTR's.
  36.             o bug fix in so_usr() and so_printf() so that 
  37.             struct/union params are printed as pointers properly.
  38.  
  39.  
  40.     PUBLIC DOMAIN SOFTWARE
  41.  
  42.     Sherlock, including the SPP, SDEL and SDIF programs, was placed in
  43.     the public domain on June 15, 1991, by its author,
  44.  
  45.         Edward K. Ream
  46.         166 North Prospect Ave.
  47.         Madison, WI 53705.
  48.         (608) 257-0802
  49.  
  50.     Sherlock may be used for any commercial or non-commercial purpose.
  51.  
  52.  
  53.     DISCLAIMER OF WARRANTIES
  54.  
  55.     Edward K. Ream (Ream) specifically disclaims all warranties,
  56.     expressed or implied, with respect to this computer software,
  57.     including but not limited to implied warranties of merchantability
  58.     and fitness for a particular purpose.  In no event shall Ream be
  59.     liable for any loss of profit or any commercial damage, including
  60.     but not limited to special, incidental consequential or other damages.
  61. */
  62.  
  63. #include "spp.h"
  64.  
  65. #define TRACE_SCOPE(name) TRACEP(name, printf("(%s)\n", pr_scope(scope)))
  66.  
  67. /*
  68.     Information about the declaration currently being parsed.
  69.  
  70.     cur_fid is the "default" holding place for identifiers.
  71.     cur_pid is used for identifiers in parameter lists.
  72.  
  73.     cur_hxtype is the type of the common head for funcs or params.
  74. */
  75. static bool     cur_typedef = FALSE;    /* TRUE if typedef seen.    */
  76.  
  77. static en_tokens cur_hptype = K_INT;    /* Common head param type.    */
  78. static en_tokens cur_hftype = K_INT;    /* Common head func type.    */
  79.  
  80. static en_tokens cur_ptype = NULL_TOK;    /* Effective param type.    */
  81. static en_tokens cur_ftype = NULL_TOK;    /* Effective func  type.    */
  82.  
  83. static char *     cur_pid;        /* Defined param id.        */
  84. static char *     cur_fid;        /* Current (func) id.        */
  85.  
  86. /*
  87.     Information about the function whose body is being parsed.
  88. */
  89. static en_tokens fn_type = NULL_TOK;    /* Effective printf type.    */
  90. static bool     fn_enable;        /* Enable generation of macros.    */
  91. static bool     fn_gen;        /* Macros generated flag.    */
  92. static bool     fn_warn;        /* Warning generated flag.    */
  93.  
  94. static struct param {
  95.     char *         p_name;
  96.     en_tokens    p_type;
  97. };
  98.  
  99. /*
  100.     Define the table of formal parameters.
  101.     This table is created in NEW_PARAM_SCOPE and OLD_PARAM_SCOPE.
  102.     Entries in the table are make by sd_comma() and sd_end().
  103. */
  104.  
  105. #define MAX_FPARAM 100
  106. static struct param pst [MAX_FPARAM];
  107. static int n_param = 0;
  108.  
  109. /*
  110.     Forward declarations of functions.
  111. */
  112. void    so_printf    (void);
  113. void    so_usr        (void);
  114. en_tokens new_type    (en_tokens old_tok, en_tokens new_tok);
  115.  
  116.  
  117. /* Return TRUE if tok is a base type or pointer or function */
  118.  
  119. /* 2/10/89 bug fix:
  120.  
  121.     If this routine does not allow STRING_TOK as a base type, then
  122.     the special casing of typedef char * charp does not work properly.
  123. */
  124. bool
  125. is_base(en_tokens tok)
  126. {
  127.     return    tok == K_CHAR   || tok == K_DOUBLE ||
  128.         tok == K_FLOAT  || tok == K_INT    ||
  129.         tok == K_LONG   || tok == K_SHORT  ||
  130.         tok == K_STRUCT || tok == K_UNION  ||
  131.         tok == K_VOID   || tok == K_ENUM   ||
  132.         tok == K_UNSIGNED || tok == K_SIGNED ||
  133.         tok == STAR_TOK ||
  134.         tok == STRING_TOK ||        /* bug fix: 2/10/89 */
  135.         tok == UNSIGNED_LONG ||        /* bug fix: 2/10/89 */
  136.         tok == K_BOOL ||        /* bug fix: 2/17/89 */
  137.         tok == LPAREN_TOK || tok == LBRACK_TOK;
  138. }
  139.  
  140. /* Return TRUE if the current token is either a base type or a typedef'd id. */
  141. bool
  142. is_type(void)
  143. {
  144.     TRACETOK("is_type");
  145.  
  146.     /* Allow local keywords here. */
  147.     allow_mkeys();
  148.     if (token == ID_TOK) {
  149.         RETURN_BOOL("is_type", is_typedef(t_symbol));
  150.     }
  151.     else {
  152.         RETURN_BOOL("is_type", is_kdecl(token));
  153.     }
  154. }
  155.  
  156. /* Return TRUE if id is a typedef'd id. */
  157. bool
  158. is_typedef(char * id)
  159. {
  160.     en_tokens type;
  161.     bool td_flag;
  162.  
  163.     TRACEP("is_typedef", printf("(%s)\n", id));
  164.  
  165.     if (st_lookup(id, &type, &td_flag) == FALSE) {
  166.         TRACEPN("is_typedef", printf("returns FALSE\n"));
  167.         return FALSE;
  168.     }
  169.     else {
  170.         TRACEPN("is_typedef", printf("returns %d\n", td_flag));
  171.         return td_flag;
  172.     }
  173. }
  174.  
  175. /*
  176.     D e c l a r a t i o n    R o u t i n e s.
  177. */
  178.  
  179. /* Begin/end a declaration. */
  180. void
  181. sd_dcl(en_scope scope)
  182. {
  183.     TRACE_SCOPE("sd_dcl");
  184.  
  185.     if (scope == OUTER_SCOPE) {
  186.         n_param    = 0;
  187.         fn_type    = NULL_TOK;
  188.         fn_name    = "";
  189.     }
  190.     if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
  191.         cur_typedef = FALSE;
  192.         cur_hptype = K_INT;
  193.         cur_hftype = K_INT;
  194.         cur_ptype  = NULL_TOK;
  195.         cur_ftype  = NULL_TOK;
  196.         cur_pid    = "";
  197.         cur_fid    = "";
  198.     }
  199. }
  200.  
  201. void
  202. sd_end(en_scope scope, en_tokens end_tok)
  203. {
  204.     int i;
  205.  
  206.     TRACEP("v", printf("(%s, %s)\n",
  207.         pr_scope(scope), pr_op(end_tok)));
  208.  
  209.     if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
  210.         if (cur_typedef) {
  211.  
  212.             TRACEPN("sd_end",
  213.                 printf("*****typedef id:  %s\n\n", cur_fid));
  214.  
  215.             /* 2/27/89: Convert typedef int bool to K_BOOL */
  216.             if (cur_ftype == K_INT && str_eq(cur_fid, "bool")) {
  217.                 cur_ftype = K_BOOL;
  218.             }
  219.             st_enter(cur_fid, cur_ftype, TRUE);
  220.         }
  221.         if (end_tok == COMMA_TOK) {
  222.             cur_fid = "";
  223.             cur_ftype = cur_hftype;
  224.         }
  225.  
  226.         /* bug fix: 2/14/18 */
  227.         cur_hftype = K_INT;
  228.     }
  229.     else if (scope == NEW_FORMAL_SCOPE) {
  230.         if (!str_eq(cur_pid, "")) {
  231.  
  232.             TRACEPN("sd_end",
  233.                 printf("new formal: %s %s\n",
  234.                     pr_op(cur_ptype), cur_pid));
  235.  
  236.             /* Enter the id into list of formal parameters. */
  237.             pst [n_param] . p_name = cur_pid;
  238.             pst [n_param] . p_type = cur_ptype;
  239.             n_param++;
  240.         }
  241.         
  242.         /* There is no common type in NEW_FORMAL_SCOPE. */
  243.         cur_pid   = "";
  244.         cur_ptype = NULL_TOK;
  245.  
  246.         /* bug fix: 2/14/89 */
  247.         cur_hptype = K_INT;
  248.     }
  249.     else if (scope == OLD_FORMAL_SCOPE) {
  250.         if (!str_eq(cur_pid, "")) {
  251.             /* Find the variable on the list of formals. */
  252.             for (i = 0; i < n_param; i++) {
  253.                 if (str_eq(cur_pid, pst[i].p_name)) {
  254.                     break;
  255.                 }
  256.             }
  257.             if (i == n_param) {
  258.                 err_cont();
  259.                 err2(    "Missing from formal param list: ",
  260.                     cur_pid);
  261.             }
  262.             else if (pst[i]. p_type != NULL_TOK) {
  263.                 err_cont();
  264.                 err2(    "Duplicate declaration of: ",
  265.                     cur_pid);
  266.             }
  267.             else {
  268.                 TRACEPN("sd_end",
  269.                     printf("old formal: %s %s\n",
  270.                         pr_op(cur_ptype), cur_pid));
  271.                 
  272.                 pst[i].p_type = cur_ptype;
  273.             }
  274.         }
  275.         if (end_tok == COMMA_TOK) {
  276.             cur_pid = "";
  277.             cur_ptype = cur_hptype;
  278.         }
  279.  
  280.         /* bug fix: 2/14/89 */
  281.         else {
  282.             cur_hptype = K_INT;
  283.         }
  284.     }
  285. }
  286.  
  287. /*
  288.     Begin a function definition.
  289.     This is called just after the opening curly bracket of the function.
  290. */
  291. void
  292. sd_func(void)
  293. {
  294.     int i;
  295.  
  296.     /* Save the current settings. */
  297.     fn_name   = cur_fid;
  298.     if (cur_ftype == NULL_TOK) {
  299.         fn_type = cur_hftype;
  300.     }
  301.     else {
  302.         fn_type = cur_ftype;
  303.     }
  304.  
  305.     /* 2/16/89:
  306.         For this function:
  307.         1. enable generation of Sherlock macros and
  308.         2. indicate that no Sherlock macro has been generated yet.
  309.         3. indicate that no warning has been generated yet. 
  310.     */
  311.     fn_enable = TRUE;
  312.     fn_gen    = FALSE;
  313.     fn_warn   = FALSE;
  314.  
  315.     /*    2/14/89
  316.         Give error message for undefined formal types.
  317.     */
  318.     for (i = 0; i < n_param; i++) {
  319.         if (pst[i].p_type == NULL_TOK) {
  320.             warn2("Missing declaration for formal parameter: ",
  321.                 pst[i].p_name);
  322.         }
  323.     }
  324.  
  325.     TRACEP("sd_func",
  326.         printf("function: %s type: %s\n", fn_name, pr_op(fn_type));
  327.         for (i = 0; i < n_param; i++) {
  328.             printf("param %d: %s type: %s\n",
  329.                 i, pst[i].p_name, pr_op(pst[i].p_type));
  330.         };
  331.     );
  332. }
  333.  
  334. /* Set the common header type of the current (sub) declaration. */
  335. void
  336. sd_htype(en_scope scope, en_tokens tok)
  337. {
  338.     bool flag;
  339.  
  340.     if (tok == ID_TOK) {
  341.         /* Get the type from an already defined typedef id. */
  342.         st_lookup(t_symbol, &tok, &flag);
  343.     }
  344.     if (!is_base(tok)) {
  345.         return;
  346.     }
  347.  
  348.     TRACEP("sd_htype",
  349.         printf("(%s, %s)\n", pr_scope(scope), pr_op(tok)));
  350.  
  351.     if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
  352.         /* Set function type. */
  353.         if (tok != LPAREN_TOK) {
  354.             /* bug fix:  2/14/89 and 12/11/90 */
  355.             if (!flag) {
  356.                 tok = new_type(cur_hftype, tok);
  357.             }
  358.             cur_hftype = tok;
  359.             cur_ftype  = tok;
  360.         }
  361.     }
  362.     else if (scope == NEW_FORMAL_SCOPE || scope == OLD_FORMAL_SCOPE) {
  363.  
  364.         /* Set formal type. */
  365.         /* bug fix: 12/11/90 */
  366.         if (!flag) {
  367.             tok = new_type(cur_hptype, tok);
  368.         }
  369.         cur_hptype = tok;
  370.         cur_ptype  = tok;
  371.     }
  372. }
  373.  
  374. /*
  375.     Set the type of the current (sub) declaration.
  376.     Token may be LPAREN_TOK or LBRACK_TOK.
  377. */
  378. void
  379. sd_type(en_scope scope, en_tokens tok)
  380. {
  381.     bool garbage;
  382.     en_tokens old_tok;
  383.  
  384.     if (tok == ID_TOK) {
  385.         /* Get the type from an already defined typedef id. */
  386.         st_lookup(t_symbol, &tok, &garbage);
  387.     }
  388.     if (!is_base(tok)) {
  389.         return;
  390.     }
  391.  
  392.     TRACEP("sd_type", printf("(%s, %s)\n", pr_scope(scope), pr_op(tok)));
  393.  
  394.     if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
  395.  
  396.         old_tok = (cur_ftype == NULL_TOK) ? cur_hftype : cur_ftype;
  397.  
  398.         /* bug fix:  2/14/89 */
  399.         cur_ftype = new_type(old_tok, tok);
  400.     }
  401.     else if (scope == NEW_FORMAL_SCOPE || scope == OLD_FORMAL_SCOPE) {
  402.  
  403.         old_tok = (cur_ptype == NULL_TOK) ? cur_hptype : cur_ptype;
  404.  
  405.         /* bug fix: 2/14/89 */
  406.         cur_ptype = new_type(old_tok, tok);
  407.     }
  408. }
  409.  
  410. /*
  411.     Compute the new print type, based on the old and new tokens.
  412.  
  413.     OLD        NEW        RESULT
  414.     unsigned    long        unsigned_long
  415.     unsigned    int        unsigned
  416.     unsigned    short        unsigned
  417.     unsigned    char        char
  418.     long        int        long
  419.     char        *        string
  420.     any        (        old_tok
  421. */
  422. static en_tokens
  423. new_type(en_tokens old_tok, en_tokens new_tok)
  424. {
  425.     en_tokens tok;
  426.  
  427.     TRACEPB("new_type", printf("(%s, %s)\n",
  428.         pr_op(old_tok), pr_op(new_tok)));
  429.  
  430.     if (new_tok == LPAREN_TOK) {
  431.         tok = old_tok;
  432.     }
  433.     else if (old_tok == K_CHAR && new_tok == STAR_TOK) {
  434.         tok = STRING_TOK;
  435.     }
  436.     /* 9/14/90: bug fix: */
  437.     else if (new_tok == STAR_TOK) {
  438.         tok = STAR_TOK;
  439.     }
  440.     else if (old_tok == UNSIGNED_LONG) {
  441.         /* unsigned long and unsigned long int. */
  442.         tok = UNSIGNED_LONG;
  443.     }
  444.     else if (old_tok == K_UNSIGNED && new_tok == K_LONG) {
  445.         tok = UNSIGNED_LONG;
  446.     }
  447.     else if (old_tok == K_UNSIGNED && new_tok == K_CHAR) {
  448.         tok = K_CHAR;
  449.     }
  450.     else if (old_tok == K_UNSIGNED) {
  451.         /* unsigned int or unsigned short. */
  452.         tok = K_UNSIGNED;
  453.     }
  454.     else if (old_tok == K_LONG && new_tok == K_INT) {
  455.         tok = K_LONG;
  456.     }
  457.     else {    
  458.         tok = new_tok;
  459.     }
  460.     TRACEPX("new_type", printf("returns: %s\n", pr_op(tok)));
  461.     return tok;
  462. }
  463.  
  464. /* Set the typedef flag. */
  465. void
  466. sd_typedef(en_scope scope)
  467. {
  468.     TRACE_SCOPE("sd_typedef");
  469.  
  470.     if(scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
  471.         cur_typedef = TRUE;
  472.     }
  473. }
  474.  
  475. /* Handle an identifier. */
  476. void
  477. sd_id(en_scope scope, char * id)
  478. {
  479.     TRACEP("sd_id", printf("(%s, %s)\n", pr_scope(scope), id));
  480.  
  481.     if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {    
  482.         cur_fid = str_alloc(id);
  483.     }
  484.     else if (scope == NEW_FORMAL_SCOPE || scope == OLD_FORMAL_SCOPE) {
  485.         cur_pid = str_alloc(id);
  486.     }
  487. }
  488.  
  489. /*
  490.     F l o w    C o n t r o l    R o u t i n e s.
  491. */
  492.  
  493. /* Define format of entries in flow control stack. */
  494.  
  495. static struct flow_node {
  496.     en_tokens    f_type;        /* Statement type.    */
  497.     int        f_status;    /* Termination info.    */
  498. };
  499.  
  500. /* Define bits in f_term field of flow_node. */
  501.  
  502. #define FALL_BIT    0x01        /* 1 if WILL fall through.    */
  503. #define ELSE_BIT    0x02        /* 1 if else clause seen.    */
  504. #define DEFAULT_BIT    0x04        /* 1 if default seen.        */
  505. #define BREAK_BIT    0x08
  506. #define NULL_FOR_BIT    0x10        /* 1 if empty for control.    */
  507.  
  508. #define MAX_FLOW 100
  509. static struct flow_node sf_nodes [MAX_FLOW];
  510. static int sf_level;        /* Current nesting level.        */
  511.  
  512. /*
  513.     Initialize the flow control.
  514.     An empty body will get a LEAVE macro.
  515. */
  516. void
  517. sf_1body(void)
  518. {
  519.     struct flow_node * p;
  520.  
  521.     sf_level = 0;
  522.     p = & sf_nodes [sf_level];
  523.     p -> f_type   = NULL_TOK;
  524.     p -> f_status = FALL_BIT;
  525. }
  526.  
  527. void
  528. sf_2body(void)
  529. {
  530.     if (sf_level != 0) {
  531.         syserr("sf_2body: can't happen\n");
  532.     }
  533. }
  534.  
  535. void
  536. sf_break(void)
  537. {
  538.     int i;
  539.     en_tokens type;
  540.  
  541.     /* Set flag showing that the enclosing loop does NOT terminate. */
  542.     for (i = sf_level; i >= 0; i--) {
  543.         type = sf_nodes [i] . f_type;
  544.         if (type == K_DO || type == K_FOR ||
  545.             type == K_WHILE || type == K_SWITCH) {
  546.             sf_nodes [i].f_status |= BREAK_BIT;
  547.             break;
  548.         }
  549.         else if (type == K_IF) {
  550.             sf_nodes [i].f_status |= BREAK_BIT;
  551.         }
  552.     }
  553. }
  554.  
  555. void
  556. sf_1do(void)
  557. {
  558.     struct flow_node * p;
  559.  
  560.     if (sf_level >= MAX_FLOW) {
  561.         warning("Statements nested too deeply\n");
  562.     }
  563.     else {
  564.         p = & sf_nodes [++sf_level];
  565.         p -> f_type   = K_DO;
  566.         p -> f_status = 0;
  567.     }
  568. }
  569.  
  570. void
  571. sf_2do(void)
  572. {
  573.     sf_level--;
  574.     sf_nodes [sf_level].f_status |= FALL_BIT;    /* Never terminates. */
  575. }
  576.  
  577. void
  578. sf_expr(void)
  579. {
  580.     sf_nodes [sf_level].f_status |= FALL_BIT;    /* Never terminates. */
  581. }
  582.  
  583. void
  584. sf_1for(bool empty_flag)
  585. {
  586.     struct flow_node * p;
  587.  
  588.     if (sf_level >= MAX_FLOW) {
  589.         warning("Statements nested too deeply\n");
  590.     }
  591.     else {
  592.         p = & sf_nodes [++sf_level];
  593.         p -> f_type   = K_DO;
  594.         p -> f_status = 0;
  595.         if (empty_flag) {
  596.             p -> f_status |= NULL_FOR_BIT;
  597.         }
  598.     }
  599. }
  600.  
  601. void
  602. sf_2for(void)
  603. {
  604.     struct flow_node *p;
  605.  
  606.     p = & sf_nodes [sf_level];
  607.     sf_level--;
  608.     if (    (p -> f_status & BREAK_BIT) ||
  609.         (p -> f_status & NULL_FOR_BIT) == 0) {
  610.         sf_nodes [sf_level].f_status |= FALL_BIT;
  611.     }
  612.     else {
  613.         sf_nodes [sf_level].f_status &= ~FALL_BIT;
  614.     }
  615. }
  616.  
  617. void
  618. sf_goto(void)
  619. {
  620.     /* goto's NEVER fall through, but labels ALWAYS do. */
  621.     sf_nodes [sf_level].f_status &= ~FALL_BIT;
  622. }
  623.     
  624.  
  625. void
  626. sf_1if(void)
  627. {
  628.     struct flow_node * p;
  629.  
  630.     if (sf_level >= MAX_FLOW) {
  631.         warning("Statements nested too deeply\n");
  632.     }
  633.     else {
  634.         p = & sf_nodes [++sf_level];
  635.         p -> f_type   = K_IF;
  636.         p -> f_status = 0;
  637.     }
  638. }
  639.  
  640. void
  641. sf_2if(void)
  642. {
  643.     struct flow_node * p;
  644.  
  645.     /*
  646.         Only set ELSE_BIT if the 'then' clause terminated.
  647.     */
  648.     p = & sf_nodes [sf_level];
  649.     if ( (p -> f_status & FALL_BIT) == 0) {
  650.         p -> f_status |= ELSE_BIT;
  651.     }
  652. }
  653.  
  654. void
  655. sf_3if(void)
  656. {
  657.     struct flow_node * p;
  658.  
  659.     /* Both braches must have terminated. */
  660.     p = & sf_nodes [sf_level];
  661.     sf_level--;
  662.     if (    (p -> f_status & ELSE_BIT) == 0 ||
  663.         (p -> f_status & BREAK_BIT) ||
  664.         (p -> f_status & FALL_BIT)) {
  665.         sf_nodes [sf_level].f_status |= FALL_BIT;
  666.     }
  667.     else {
  668.         sf_nodes [sf_level].f_status &= ~FALL_BIT;
  669.     }
  670. }
  671.  
  672. void
  673. sf_label(void)
  674. {
  675.     sf_nodes [sf_level].f_status |= FALL_BIT;
  676. }
  677.  
  678. void
  679. sf_return(void)
  680. {
  681.     sf_nodes [sf_level].f_status &= ~FALL_BIT;
  682. }
  683.  
  684. void
  685. sf_1switch(void)
  686. {
  687.     struct flow_node * p;
  688.  
  689.     if (sf_level >= MAX_FLOW) {
  690.         warning("Statements nested too deeply\n");
  691.     }
  692.     else {
  693.         p = & sf_nodes [++sf_level];
  694.         p -> f_type   = K_SWITCH;
  695.         p -> f_status = 0;
  696.     }
  697. }
  698.  
  699. void
  700. sf_default(void)
  701. {
  702.     sf_nodes [sf_level].f_status |= DEFAULT_BIT;
  703. }
  704.  
  705. void
  706. sf_2switch(void)
  707. {
  708.     struct flow_node * p;
  709.  
  710.     p = & sf_nodes [sf_level];
  711.     sf_level--;
  712.     if (    (p -> f_status & DEFAULT_BIT) == 0 ||
  713.         (p -> f_status & BREAK_BIT) ||
  714.         (p -> f_status & FALL_BIT)) {
  715.         sf_nodes [sf_level].f_status |= FALL_BIT;
  716.     }
  717.     else {
  718.         sf_nodes [sf_level].f_status &= ~FALL_BIT;
  719.     }
  720. }
  721.  
  722. void
  723. sf_1while(void)
  724. {
  725.     struct flow_node * p;
  726.  
  727.     if (sf_level >= MAX_FLOW) {
  728.         warning("Statements nested too deeply\n");
  729.     }
  730.     else {
  731.         p = & sf_nodes [++sf_level];
  732.         p -> f_type   = K_WHILE;
  733.         p -> f_status = 0;
  734.     }
  735. }
  736.  
  737. void
  738. sf_2while(void)
  739. {
  740.     sf_nodes [--sf_level].f_status |= FALL_BIT;    /* Never terminates. */
  741. }
  742.  
  743. /*
  744.     O u t p u t    R o u t i n e s.
  745. */
  746. static char * out_type(en_tokens tok, bool flag);
  747.  
  748. /*
  749.     Disable generation of Sherlock macros, but ONLY if we are not
  750.     already generating them!!
  751.     This is done by disabling so_entry(), so_?exit() and so_leave().
  752. */
  753. void
  754. so_disable(void)
  755. {
  756.     TICK("so_disable");
  757.  
  758.     /* bug fix: 2/25/89. */
  759.     if (fn_gen && fn_enable) {
  760.         if (!fn_warn) {
  761.             warning("Sherlock macros generated for this function");
  762.         }
  763.         fn_warn = TRUE;
  764.     }
  765.     else {
  766.         fn_enable = FALSE;
  767.     }
  768. }
  769.  
  770. /* Ouput the cumulative newline count. */
  771.  
  772. static void
  773. so_cnl(void)
  774. {
  775.     int i, count;
  776.  
  777.     count = min(cnl_count, 2);
  778.     for (i = 0; i < count; i++) {
  779.         sysnlput();
  780.     }
  781.     cnl_count = 0;
  782. }
  783.  
  784. /* Output held white space. */
  785. static void
  786. so_hws(void)
  787. {
  788.     int i;
  789.  
  790.     for (i = 0; i < hws_count; i++) {
  791.         syscput(hws_buf[i]);
  792.     }
  793.     hws_count = 0;
  794. }
  795.  
  796. /* Output leading white space. */
  797. static void
  798. so_lws(void)
  799. {
  800.     int i;
  801.  
  802.     for (i = 0; i < lws_count; i++) {
  803.         syscput(lws_buf[i]);
  804.     }
  805. }
  806.  
  807. /* Output the entry macro. */
  808. void
  809. so_entry(void)
  810. {
  811.     char *p;
  812.  
  813.     /* 3/5/89 */
  814.     if (m_flag) {
  815.         warning("Macro found where entry macro should be");
  816.     }
  817.  
  818.     if (!fn_enable || !entry_flag || m_flag || t_inlevel != 0) {
  819.         return;
  820.     }
  821.  
  822.     TRACEPB("so_entry", printf("(%s)\n", fn_name));
  823.  
  824.     fn_gen = TRUE;
  825.  
  826.     if (last_tok == LCURLY_TOK) {
  827.         /* There are no local declarations. */
  828.         sysnlput();
  829.         so_lws();
  830.     }
  831.     else if (last_tok == SEMICOLON_TOK) {
  832.         /* There ARE local declarations. */
  833.         sysnlput();
  834.         sysnlput();
  835.         so_lws();
  836.     }
  837.     else {
  838.         warning("so_entry:  can't happen");
  839.         printf("last_tok: %d\n", last_tok);
  840.         sysnlput(); sysnlput();
  841.         so_lws();
  842.     }
  843.  
  844.     /* Special case the main routine. */
  845.     if (str_eq(fn_name, "main")) {
  846.         syssput(s_init);
  847.         syssput("();\n");
  848.         so_lws();
  849.         syssput(s_parse);
  850.         syssput("(argc, argv, \"++\", \"--\");\n\n");
  851.         so_lws();
  852.     }
  853.  
  854.     if (n_param == 0) {
  855.         if (tick_flag) {
  856.             syssput(tick);
  857.         }
  858.         else {
  859.             syssput(tickb);
  860.         }
  861.         syssput("(\"");
  862.         syssput(fn_name);
  863.         syssput("\");");
  864.     }
  865.     else {
  866.         if (tick_flag) {
  867.             syssput(ptrace);
  868.         }
  869.         else {
  870.             syssput(pbtrace);
  871.         }
  872.         syssput("(\"");
  873.         syssput(fn_name);
  874.         syssput("\", ");
  875.  
  876.         /* Output the params. */
  877.         if (usr_flag) {
  878.             so_usr();
  879.         }
  880.         else {
  881.             so_printf();
  882.         }
  883.     }
  884.  
  885.     /*
  886.         Output exactly one blank line unless the function
  887.         body is empty (next token is '}' or "return".
  888.  
  889.         Do NOT output a blank line in front of return so that
  890.         SDEL will work properly.
  891.     */
  892.     p = syshnldel();
  893.  
  894.     if (p == NULL || (  !str_eq(p, "}") && !str_eq(p, "return") )) {
  895.         sysnlput();
  896.         sysnlput();
  897.     }
  898.  
  899.     /* ----- Do NOT use this code!!
  900.     if (p != NULL && str_eq(p, "return")) {
  901.         sysnlput();
  902.     }
  903.     else if (p == NULL || !str_eq(p, "}")) {
  904.         sysnlput();
  905.         sysnlput();
  906.     }
  907.     ----- */
  908.  
  909.     RETURN_VOID("so_entry");
  910. }
  911.  
  912.  
  913. /* Output the parameters using the printf function. */
  914. static void
  915. so_printf(void)
  916. {
  917.     bool flag;
  918.     int i, length, newlength;    /* 3/1/89: all this logic. */
  919.     char *p;
  920.  
  921.     flag = FALSE;
  922.     length = 32 + strlen(fn_name);
  923.  
  924.     /* Output the printf format specification. */
  925.     syssput("printf(\"(");
  926.     for (i = 0; i < n_param; i++) {
  927.         p = out_type(pst[i].p_type, TRUE);
  928.         if (p != NULL) {
  929.  
  930.             /* Make sure the line would not be too long. */
  931.             length += strlen(p) + 2;
  932.             if (length >= 77 && i < n_param-1) {
  933.                 syssput("\\\n");
  934.                 length = strlen(p) + 2;
  935.                 flag = TRUE;
  936.             }
  937.  
  938.             /* Output the printf specification. */
  939.             syssput(p);
  940.             if (i < n_param - 1) {
  941.                 syssput(", ");
  942.             }
  943.         }
  944.     }
  945.  
  946.     /* End the printf format string. */
  947.     syssput(")\\n\", ");
  948.     length += 6;
  949.  
  950.     /* Go to the next line if we can't get ALL the params on it. */
  951.     for (newlength = length, i = 0; i < n_param; i++) {
  952.         newlength += strlen(pst[i].p_name) + 2;
  953.         if (pst[i].p_type == K_BOOL) {
  954.             newlength += 10; /* strlen("sl_sbout()"); */
  955.         }
  956.     }
  957.  
  958.     if (newlength >= 77 || flag) {
  959.         syssput("\n\t\t");
  960.         length = 16;
  961.     };
  962.  
  963.     /* Output the list of arguments. */
  964.     for (i = 0; i < n_param; i++) {
  965.         p = out_type(pst[i].p_type, FALSE);
  966.         if (p != NULL) {
  967.  
  968.             /* Compute the new length of the line. */
  969.             length += strlen(pst[i].p_name) + 2;
  970.             if (pst[i].p_type == K_BOOL) {
  971.                 length += 10; /* strlen("sl_sbout()"); */
  972.             }
  973.             /* 6/27/89 */
  974.             else if (    pst[i].p_type == K_STRUCT ||
  975.                     pst[i].p_type == K_UNION
  976.                 ) {
  977.                 length++;
  978.             }
  979.  
  980.             /* Go to a new line if it would be too long. */
  981.             if (length >= 77 && i < n_param - 1) {
  982.                 syssput("\n\t\t");
  983.                 length = 16;
  984.             }
  985.  
  986.             /* 6/27/89 */
  987.             if (    pst[i].p_type == K_STRUCT ||
  988.                 pst[i].p_type == K_UNION
  989.                ) {
  990.                 syscput('&');
  991.             }
  992.  
  993.             /* 2/27/89 */
  994.             if (pst[i].p_type == K_BOOL) {
  995.                 syssput("sl_sbout(");
  996.                 syssput(pst[i].p_name);
  997.                 syssput(")");
  998.             }
  999.             else {
  1000.                 syssput(pst[i].p_name);
  1001.             }
  1002.             if (i < n_param - 1) {
  1003.                 syssput(", ");
  1004.             }
  1005.         }
  1006.     }
  1007.     syssput("));");
  1008. }
  1009.  
  1010. static void
  1011. so_usr(void)
  1012. {
  1013.     int i;
  1014.     int length;    /* 3/1/89: all this logic. */
  1015.  
  1016.     syssput(" sl_lpout();\n\t\t");
  1017.     length = 16;
  1018.  
  1019.     for (i = 0; i < n_param; i++) {
  1020.  
  1021.         length += (strlen(pst[i].p_name) + 24);
  1022.         if (length > 77) {
  1023.             syssput("\n\t\t");
  1024.             length = 16 + strlen(pst[i].p_name) + 24;
  1025.         }
  1026.  
  1027.         switch(pst[i].p_type) {
  1028.         case K_CHAR:        syssput("sl_cout("); break;
  1029.         case K_BOOL:        syssput("sl_bout("); break;
  1030.         case K_UNSIGNED:    syssput("sl_uiout("); break;
  1031.         case UNSIGNED_LONG:    syssput("sl_ulout("); break;
  1032.         case K_SIGNED:
  1033.         case K_ENUM:
  1034.         case K_SHORT:
  1035.         case K_INT:        syssput("sl_iout("); break;
  1036.         case K_LONG:        syssput("sl_lout("); break;
  1037.         case STRING_TOK:    syssput("sl_sout("); break;
  1038.         case K_STRUCT:
  1039.         case K_UNION:
  1040.         case LPAREN_TOK:
  1041.         case LBRACK_TOK:
  1042.         case STAR_TOK:        syssput("sl_pout("); break;
  1043.         case K_DOUBLE:
  1044.         case K_FLOAT:        syssput("sl_fout("); break;
  1045.         default:
  1046.             warning("Unknown parameter type: int assumed");
  1047.             syssput("sl_iout(");
  1048.         }
  1049.  
  1050.         /* 6/27/89 */
  1051.         if (pst[i].p_type == K_STRUCT || pst[i].p_type == K_UNION) {
  1052.             syscput('&');
  1053.         }
  1054.         syssput(pst[i].p_name);
  1055.         syscput(')');
  1056.         if (i < n_param - 1) {
  1057.             /* 2/14/89 */
  1058.             syssput("; sl_csout(); ");
  1059.         }
  1060.     }
  1061.  
  1062.     /* 2/14/89 */
  1063.     syssput("; sl_rpout());");
  1064. }
  1065.  
  1066. static bool old_m;
  1067. static bool m_warn;
  1068.  
  1069. void
  1070. so_1exit(void)
  1071. {
  1072.     /* 2/16/89 */
  1073.     SL_DISABLE();
  1074.  
  1075.     if (!fn_enable) {
  1076.         return;
  1077.     }
  1078.  
  1079.     old_m = m_flag;
  1080.     m_warn = FALSE;
  1081.  
  1082.     if (m_flag) {
  1083.         warning("Return inside macro expansion");
  1084.         m_warn = TRUE;
  1085.     }
  1086.  
  1087.     if (!exit_flag || m_flag || old_m || t_inlevel != 0) {
  1088.         return;
  1089.     }
  1090.  
  1091.     TRACEPB("so_1exit", printf("(%s)\n", fn_name));
  1092.  
  1093.     fn_gen = TRUE;
  1094.  
  1095.     /* Kill the hold buffer. */
  1096.     syshkill();
  1097.  
  1098.     /* Output appropriate white space. */
  1099.     if (first_tok) {
  1100.         /* -----
  1101.         sysnlput();
  1102.         so_lws();
  1103.         ----- */
  1104.         so_cnl();
  1105.         so_lws();
  1106.     }
  1107.     else {
  1108.         so_hws();
  1109.     }
  1110.  
  1111.     RETURN_VOID("so_1exit");
  1112. }
  1113.  
  1114. /* Flag is TRUE if an expression exists. */
  1115. void
  1116. so_2exit(bool flag)
  1117. {
  1118.     en_tokens type;
  1119.  
  1120.     /* 2/16/89 */
  1121.     SL_DISABLE();
  1122.  
  1123.     /* Don't worry about current macro expansions, only old ones. */
  1124.     if (!fn_enable || !exit_flag || old_m || t_inlevel != 0) {
  1125.         return;
  1126.     }
  1127.  
  1128.     TRACEPB("so_2exit", printf("%s, flag: %d\n", fn_name, flag));
  1129.  
  1130.     fn_gen = TRUE;
  1131.  
  1132.     /* Generate just a return if tick_flag is true. */
  1133.     if (tick_flag) {
  1134.         syssput("return");
  1135.         RETURN_VOID("so_2exit");
  1136.     }
  1137.  
  1138.     /*
  1139.         Generate a warning and RETURN_VOID macro for returns without
  1140.         expressions in non-void type functions.
  1141.     */
  1142.     if (!flag && fn_type != K_VOID) {
  1143.         warning("Void return from function of non-void type");
  1144.         type = K_VOID;
  1145.     }
  1146.     else {
  1147.         type = fn_type;
  1148.     }
  1149.  
  1150.     TRACEP("so_2exit", printf("type: %s\n", pr_op(type)));
  1151.  
  1152.     switch(type) {
  1153.  
  1154.     case K_VOID:     syssput(r_void);    break;
  1155.     case K_CHAR:     syssput(r_char);    break;
  1156.     case K_BOOL:     syssput(r_bool);    break;
  1157.     case K_UNSIGNED: syssput(r_uint);    break;    /* bug fix: 2/10/89 */
  1158.     case UNSIGNED_LONG:
  1159.              syssput(r_ulong);    break;    /* bug fix: 2/10/89 */
  1160.     case K_ENUM:
  1161.     case K_SIGNED:
  1162.     case K_SHORT:
  1163.     case K_INT:     syssput(r_int);    break;
  1164.     case K_LONG:     syssput(r_long);    break;
  1165.     case STRING_TOK: syssput(r_string);    break;
  1166.     case K_STRUCT:
  1167.     case K_UNION:
  1168.             sysnlput();        /* bug fix: 6/27/89 */
  1169.             so_lws();
  1170.             syssput(tickx);
  1171.             break;
  1172.     case LPAREN_TOK:
  1173.     case LBRACK_TOK:
  1174.     case STAR_TOK:     syssput(r_ptr);    break;
  1175.     case K_FLOAT:     syssput(r_float);    break;
  1176.     case K_DOUBLE:     syssput(r_double);    break;
  1177.  
  1178.     default:        
  1179.         warning("Unknown expression type--no RETURN macro generated");
  1180.         syssput("return");
  1181.         break;
  1182.     }
  1183.  
  1184.     /* Output function name. */
  1185.     syssput("(\"");
  1186.     syssput(fn_name);
  1187.     syscput('"');
  1188.  
  1189.     /* Structs and unions are handled as follows:
  1190.         TICKX(function name);
  1191.         return ...
  1192.     */
  1193.     if (type == K_STRUCT || type == K_UNION) {
  1194.         syssput(");");
  1195.         sysnlput();
  1196.         so_lws();
  1197.         syssput("return");
  1198.     }
  1199.         
  1200.     /*
  1201.         Output a comma for all types except void, struct or union.
  1202.         No white space is needed because the white space after
  1203.         the original "return" will be used.
  1204.     */
  1205.     if (type != K_VOID && type != K_STRUCT && type != K_UNION) {
  1206.         syscput(',');
  1207.     }
  1208.  
  1209.     LEAVE("so_2exit");
  1210. }
  1211.  
  1212. void
  1213. so_3exit(void)
  1214. {
  1215.     /* 2/16/89 */
  1216.     SL_DISABLE();
  1217.  
  1218.     if (!fn_enable) {
  1219.         return;
  1220.     }
  1221.  
  1222.     ENTER("so_3exit");
  1223.  
  1224.     fn_gen = TRUE;
  1225.  
  1226.     /*
  1227.         Don't worry about current macro expansions, only old ones.
  1228.  
  1229.         6/27/89: Don't add anything for struct/union types.
  1230.     */
  1231.     if (    !tick_flag && exit_flag && !old_m && t_inlevel == 0 &&
  1232.         fn_type != K_STRUCT && fn_type != K_UNION
  1233.        ) {
  1234.         syscput(')');
  1235.     }
  1236.  
  1237.     RETURN_VOID("so_3exit");
  1238. }
  1239.  
  1240. void
  1241. so_leave(void)
  1242. {
  1243.     int i, count;
  1244.  
  1245.     /* 2/16/89 */
  1246.     SL_DISABLE();
  1247.  
  1248.     /* bug fix: 3/5/89 */
  1249.     if (!fn_enable || tick_flag || !exit_flag || m_flag || t_inlevel != 0) {
  1250.         return;
  1251.     }
  1252.     
  1253.     TRACEPB("so_leave", printf("(%s)\n", fn_name));
  1254.  
  1255.     fn_gen = TRUE;
  1256.     
  1257.     /* Examine flow control to see if we need anything. */
  1258.     if ((sf_nodes [0].f_status & FALL_BIT) == 0) {
  1259.         RETURN_VOID("so_leave");
  1260.     }
  1261.  
  1262.     /* Kill the buffer, containing white space and }. */
  1263.     syshkill();
  1264.  
  1265.     /* Output one blank line and leading white space. */
  1266.     sysnlput();
  1267.     sysnlput();
  1268.     so_lws();
  1269.  
  1270.     /* Output tickx macro */
  1271.     syssput(tickx);
  1272.     syssput("(\"");
  1273.     syssput(fn_name);
  1274.     syssput("\");");
  1275.  
  1276.     /* One trailing newline. */
  1277.     sysnlput();
  1278.  
  1279.     /* Output the teminating brace of the function. */
  1280.     syscput('}');
  1281.  
  1282.     RETURN_VOID("so_leave");
  1283. }
  1284.  
  1285. static char *
  1286. out_type(en_tokens type, bool flag)
  1287. {
  1288.     switch(type) {
  1289.     case K_CHAR:        return "%c";
  1290.     case K_UNSIGNED:    return "%u";    /* bug fix: 2/10/89 */
  1291.     case UNSIGNED_LONG:    return "%lu";    /* bug fix: 2/10/89 */
  1292.     case K_BOOL:        return "%s";    /* 2/27/89: sl_sbout(). */
  1293.     case K_ENUM:
  1294.     case K_SIGNED:
  1295.     case K_SHORT:
  1296.     case K_INT:        return "%d";
  1297.     case K_LONG:        return "%ld";
  1298.     case STRING_TOK:    return "%s";
  1299.     case K_STRUCT:
  1300.     case K_UNION:
  1301.     case LBRACK_TOK:
  1302.     case LPAREN_TOK:
  1303.     case STAR_TOK:        return "%p";
  1304.     case K_DOUBLE:
  1305.     case K_FLOAT:        return "%g";
  1306.     default:
  1307.         if (flag) {
  1308.             warn3(    "Unknown formal type '",
  1309.                 pr_op(type),
  1310.                 "' int assumed");
  1311.         }
  1312.         return "%d";
  1313.     }
  1314. }
  1315.  
  1316. static void
  1317. sd_dump()
  1318. {
  1319.     SL_DISABLE();
  1320.  
  1321.     printf("\n");
  1322.     printf("cur_typedef: %s\n", pr_bool(cur_typedef));
  1323.     printf("cur_hptype:  %s\n", pr_op(cur_hptype));
  1324.     printf("cur_hftype:  %s\n", pr_op(cur_hftype));
  1325.     printf("cur_ptype:   %s\n", pr_op(cur_ptype));
  1326.     printf("cur_ftype:   %s\n", pr_op(cur_ftype));
  1327.     printf("cur_pid:     %s\n", cur_pid);
  1328.     printf("cur_fid:     %s\n", cur_fid);
  1329.     printf("fn_type:     %s\n", pr_op(fn_type));
  1330.     printf("fn_name:     %s\n", fn_name);
  1331.     printf("\n");
  1332. }
  1333.