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 >
Wrap
C/C++ Source or Header
|
1991-06-09
|
28KB
|
1,333 lines
/*
New Sherlock preprocessor -- semantic routines.
Source: sem.c
Started: October 1, 1987
Version:
June 9, 1991: bug fixes originally made by Roberto Artigas
These fixes were made in 1990.
July 15, 1988
February 2, 1989: bug fixes:
is_base() make STRING_TOK a valid base type.
sd_htype() convert to string, unsigned_long.
out_type() add %u and %lu printf types.
so_2exit() call r_uint to print unsigned.
so_usr() call sl_uint to print unsigned.
February 14, 1989: bug fixes:
sd_htype(), sd_type() call new new_type() routine.
sd_end() reset cur_hptype, cur_hftype.
This makes unsigned int, unsigned short always work.
so_usr() decrease output lines and call
sl_csout(), sl_lpout(), sl_rpout().
sd_func() add error message.
February 15, 1989: changes:
so_printf() only 5 printf specs per line.
February 15, 1989: changes:
fn_enable, fn_gen, fn_warn flags added.
fn_name made global.
February 25, 1989: bug fix to so_disable.
February 27, 1989: support for sl_sbout().
March 1, 1989: better versions of so_printf() and so_usr().
March 5, 1989: bug fix in so_entry().
Version 1.4:
June 27, 1989:
o bug fix in so_2exit() so structs/unions generate
TICKX's on exit instead of RETURN_PTR's.
o bug fix in so_usr() and so_printf() so that
struct/union params are printed as pointers properly.
PUBLIC DOMAIN SOFTWARE
Sherlock, including the SPP, SDEL and SDIF programs, was placed in
the public domain on June 15, 1991, by its author,
Edward K. Ream
166 North Prospect Ave.
Madison, WI 53705.
(608) 257-0802
Sherlock may be used for any commercial or non-commercial purpose.
DISCLAIMER OF WARRANTIES
Edward K. Ream (Ream) specifically disclaims all warranties,
expressed or implied, with respect to this computer software,
including but not limited to implied warranties of merchantability
and fitness for a particular purpose. In no event shall Ream be
liable for any loss of profit or any commercial damage, including
but not limited to special, incidental consequential or other damages.
*/
#include "spp.h"
#define TRACE_SCOPE(name) TRACEP(name, printf("(%s)\n", pr_scope(scope)))
/*
Information about the declaration currently being parsed.
cur_fid is the "default" holding place for identifiers.
cur_pid is used for identifiers in parameter lists.
cur_hxtype is the type of the common head for funcs or params.
*/
static bool cur_typedef = FALSE; /* TRUE if typedef seen. */
static en_tokens cur_hptype = K_INT; /* Common head param type. */
static en_tokens cur_hftype = K_INT; /* Common head func type. */
static en_tokens cur_ptype = NULL_TOK; /* Effective param type. */
static en_tokens cur_ftype = NULL_TOK; /* Effective func type. */
static char * cur_pid; /* Defined param id. */
static char * cur_fid; /* Current (func) id. */
/*
Information about the function whose body is being parsed.
*/
static en_tokens fn_type = NULL_TOK; /* Effective printf type. */
static bool fn_enable; /* Enable generation of macros. */
static bool fn_gen; /* Macros generated flag. */
static bool fn_warn; /* Warning generated flag. */
static struct param {
char * p_name;
en_tokens p_type;
};
/*
Define the table of formal parameters.
This table is created in NEW_PARAM_SCOPE and OLD_PARAM_SCOPE.
Entries in the table are make by sd_comma() and sd_end().
*/
#define MAX_FPARAM 100
static struct param pst [MAX_FPARAM];
static int n_param = 0;
/*
Forward declarations of functions.
*/
void so_printf (void);
void so_usr (void);
en_tokens new_type (en_tokens old_tok, en_tokens new_tok);
/* Return TRUE if tok is a base type or pointer or function */
/* 2/10/89 bug fix:
If this routine does not allow STRING_TOK as a base type, then
the special casing of typedef char * charp does not work properly.
*/
bool
is_base(en_tokens tok)
{
return tok == K_CHAR || tok == K_DOUBLE ||
tok == K_FLOAT || tok == K_INT ||
tok == K_LONG || tok == K_SHORT ||
tok == K_STRUCT || tok == K_UNION ||
tok == K_VOID || tok == K_ENUM ||
tok == K_UNSIGNED || tok == K_SIGNED ||
tok == STAR_TOK ||
tok == STRING_TOK || /* bug fix: 2/10/89 */
tok == UNSIGNED_LONG || /* bug fix: 2/10/89 */
tok == K_BOOL || /* bug fix: 2/17/89 */
tok == LPAREN_TOK || tok == LBRACK_TOK;
}
/* Return TRUE if the current token is either a base type or a typedef'd id. */
bool
is_type(void)
{
TRACETOK("is_type");
/* Allow local keywords here. */
allow_mkeys();
if (token == ID_TOK) {
RETURN_BOOL("is_type", is_typedef(t_symbol));
}
else {
RETURN_BOOL("is_type", is_kdecl(token));
}
}
/* Return TRUE if id is a typedef'd id. */
bool
is_typedef(char * id)
{
en_tokens type;
bool td_flag;
TRACEP("is_typedef", printf("(%s)\n", id));
if (st_lookup(id, &type, &td_flag) == FALSE) {
TRACEPN("is_typedef", printf("returns FALSE\n"));
return FALSE;
}
else {
TRACEPN("is_typedef", printf("returns %d\n", td_flag));
return td_flag;
}
}
/*
D e c l a r a t i o n R o u t i n e s.
*/
/* Begin/end a declaration. */
void
sd_dcl(en_scope scope)
{
TRACE_SCOPE("sd_dcl");
if (scope == OUTER_SCOPE) {
n_param = 0;
fn_type = NULL_TOK;
fn_name = "";
}
if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
cur_typedef = FALSE;
cur_hptype = K_INT;
cur_hftype = K_INT;
cur_ptype = NULL_TOK;
cur_ftype = NULL_TOK;
cur_pid = "";
cur_fid = "";
}
}
void
sd_end(en_scope scope, en_tokens end_tok)
{
int i;
TRACEP("v", printf("(%s, %s)\n",
pr_scope(scope), pr_op(end_tok)));
if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
if (cur_typedef) {
TRACEPN("sd_end",
printf("*****typedef id: %s\n\n", cur_fid));
/* 2/27/89: Convert typedef int bool to K_BOOL */
if (cur_ftype == K_INT && str_eq(cur_fid, "bool")) {
cur_ftype = K_BOOL;
}
st_enter(cur_fid, cur_ftype, TRUE);
}
if (end_tok == COMMA_TOK) {
cur_fid = "";
cur_ftype = cur_hftype;
}
/* bug fix: 2/14/18 */
cur_hftype = K_INT;
}
else if (scope == NEW_FORMAL_SCOPE) {
if (!str_eq(cur_pid, "")) {
TRACEPN("sd_end",
printf("new formal: %s %s\n",
pr_op(cur_ptype), cur_pid));
/* Enter the id into list of formal parameters. */
pst [n_param] . p_name = cur_pid;
pst [n_param] . p_type = cur_ptype;
n_param++;
}
/* There is no common type in NEW_FORMAL_SCOPE. */
cur_pid = "";
cur_ptype = NULL_TOK;
/* bug fix: 2/14/89 */
cur_hptype = K_INT;
}
else if (scope == OLD_FORMAL_SCOPE) {
if (!str_eq(cur_pid, "")) {
/* Find the variable on the list of formals. */
for (i = 0; i < n_param; i++) {
if (str_eq(cur_pid, pst[i].p_name)) {
break;
}
}
if (i == n_param) {
err_cont();
err2( "Missing from formal param list: ",
cur_pid);
}
else if (pst[i]. p_type != NULL_TOK) {
err_cont();
err2( "Duplicate declaration of: ",
cur_pid);
}
else {
TRACEPN("sd_end",
printf("old formal: %s %s\n",
pr_op(cur_ptype), cur_pid));
pst[i].p_type = cur_ptype;
}
}
if (end_tok == COMMA_TOK) {
cur_pid = "";
cur_ptype = cur_hptype;
}
/* bug fix: 2/14/89 */
else {
cur_hptype = K_INT;
}
}
}
/*
Begin a function definition.
This is called just after the opening curly bracket of the function.
*/
void
sd_func(void)
{
int i;
/* Save the current settings. */
fn_name = cur_fid;
if (cur_ftype == NULL_TOK) {
fn_type = cur_hftype;
}
else {
fn_type = cur_ftype;
}
/* 2/16/89:
For this function:
1. enable generation of Sherlock macros and
2. indicate that no Sherlock macro has been generated yet.
3. indicate that no warning has been generated yet.
*/
fn_enable = TRUE;
fn_gen = FALSE;
fn_warn = FALSE;
/* 2/14/89
Give error message for undefined formal types.
*/
for (i = 0; i < n_param; i++) {
if (pst[i].p_type == NULL_TOK) {
warn2("Missing declaration for formal parameter: ",
pst[i].p_name);
}
}
TRACEP("sd_func",
printf("function: %s type: %s\n", fn_name, pr_op(fn_type));
for (i = 0; i < n_param; i++) {
printf("param %d: %s type: %s\n",
i, pst[i].p_name, pr_op(pst[i].p_type));
};
);
}
/* Set the common header type of the current (sub) declaration. */
void
sd_htype(en_scope scope, en_tokens tok)
{
bool flag;
if (tok == ID_TOK) {
/* Get the type from an already defined typedef id. */
st_lookup(t_symbol, &tok, &flag);
}
if (!is_base(tok)) {
return;
}
TRACEP("sd_htype",
printf("(%s, %s)\n", pr_scope(scope), pr_op(tok)));
if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
/* Set function type. */
if (tok != LPAREN_TOK) {
/* bug fix: 2/14/89 and 12/11/90 */
if (!flag) {
tok = new_type(cur_hftype, tok);
}
cur_hftype = tok;
cur_ftype = tok;
}
}
else if (scope == NEW_FORMAL_SCOPE || scope == OLD_FORMAL_SCOPE) {
/* Set formal type. */
/* bug fix: 12/11/90 */
if (!flag) {
tok = new_type(cur_hptype, tok);
}
cur_hptype = tok;
cur_ptype = tok;
}
}
/*
Set the type of the current (sub) declaration.
Token may be LPAREN_TOK or LBRACK_TOK.
*/
void
sd_type(en_scope scope, en_tokens tok)
{
bool garbage;
en_tokens old_tok;
if (tok == ID_TOK) {
/* Get the type from an already defined typedef id. */
st_lookup(t_symbol, &tok, &garbage);
}
if (!is_base(tok)) {
return;
}
TRACEP("sd_type", printf("(%s, %s)\n", pr_scope(scope), pr_op(tok)));
if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
old_tok = (cur_ftype == NULL_TOK) ? cur_hftype : cur_ftype;
/* bug fix: 2/14/89 */
cur_ftype = new_type(old_tok, tok);
}
else if (scope == NEW_FORMAL_SCOPE || scope == OLD_FORMAL_SCOPE) {
old_tok = (cur_ptype == NULL_TOK) ? cur_hptype : cur_ptype;
/* bug fix: 2/14/89 */
cur_ptype = new_type(old_tok, tok);
}
}
/*
Compute the new print type, based on the old and new tokens.
OLD NEW RESULT
unsigned long unsigned_long
unsigned int unsigned
unsigned short unsigned
unsigned char char
long int long
char * string
any ( old_tok
*/
static en_tokens
new_type(en_tokens old_tok, en_tokens new_tok)
{
en_tokens tok;
TRACEPB("new_type", printf("(%s, %s)\n",
pr_op(old_tok), pr_op(new_tok)));
if (new_tok == LPAREN_TOK) {
tok = old_tok;
}
else if (old_tok == K_CHAR && new_tok == STAR_TOK) {
tok = STRING_TOK;
}
/* 9/14/90: bug fix: */
else if (new_tok == STAR_TOK) {
tok = STAR_TOK;
}
else if (old_tok == UNSIGNED_LONG) {
/* unsigned long and unsigned long int. */
tok = UNSIGNED_LONG;
}
else if (old_tok == K_UNSIGNED && new_tok == K_LONG) {
tok = UNSIGNED_LONG;
}
else if (old_tok == K_UNSIGNED && new_tok == K_CHAR) {
tok = K_CHAR;
}
else if (old_tok == K_UNSIGNED) {
/* unsigned int or unsigned short. */
tok = K_UNSIGNED;
}
else if (old_tok == K_LONG && new_tok == K_INT) {
tok = K_LONG;
}
else {
tok = new_tok;
}
TRACEPX("new_type", printf("returns: %s\n", pr_op(tok)));
return tok;
}
/* Set the typedef flag. */
void
sd_typedef(en_scope scope)
{
TRACE_SCOPE("sd_typedef");
if(scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
cur_typedef = TRUE;
}
}
/* Handle an identifier. */
void
sd_id(en_scope scope, char * id)
{
TRACEP("sd_id", printf("(%s, %s)\n", pr_scope(scope), id));
if (scope == OUTER_SCOPE || scope == BLOCK_SCOPE) {
cur_fid = str_alloc(id);
}
else if (scope == NEW_FORMAL_SCOPE || scope == OLD_FORMAL_SCOPE) {
cur_pid = str_alloc(id);
}
}
/*
F l o w C o n t r o l R o u t i n e s.
*/
/* Define format of entries in flow control stack. */
static struct flow_node {
en_tokens f_type; /* Statement type. */
int f_status; /* Termination info. */
};
/* Define bits in f_term field of flow_node. */
#define FALL_BIT 0x01 /* 1 if WILL fall through. */
#define ELSE_BIT 0x02 /* 1 if else clause seen. */
#define DEFAULT_BIT 0x04 /* 1 if default seen. */
#define BREAK_BIT 0x08
#define NULL_FOR_BIT 0x10 /* 1 if empty for control. */
#define MAX_FLOW 100
static struct flow_node sf_nodes [MAX_FLOW];
static int sf_level; /* Current nesting level. */
/*
Initialize the flow control.
An empty body will get a LEAVE macro.
*/
void
sf_1body(void)
{
struct flow_node * p;
sf_level = 0;
p = & sf_nodes [sf_level];
p -> f_type = NULL_TOK;
p -> f_status = FALL_BIT;
}
void
sf_2body(void)
{
if (sf_level != 0) {
syserr("sf_2body: can't happen\n");
}
}
void
sf_break(void)
{
int i;
en_tokens type;
/* Set flag showing that the enclosing loop does NOT terminate. */
for (i = sf_level; i >= 0; i--) {
type = sf_nodes [i] . f_type;
if (type == K_DO || type == K_FOR ||
type == K_WHILE || type == K_SWITCH) {
sf_nodes [i].f_status |= BREAK_BIT;
break;
}
else if (type == K_IF) {
sf_nodes [i].f_status |= BREAK_BIT;
}
}
}
void
sf_1do(void)
{
struct flow_node * p;
if (sf_level >= MAX_FLOW) {
warning("Statements nested too deeply\n");
}
else {
p = & sf_nodes [++sf_level];
p -> f_type = K_DO;
p -> f_status = 0;
}
}
void
sf_2do(void)
{
sf_level--;
sf_nodes [sf_level].f_status |= FALL_BIT; /* Never terminates. */
}
void
sf_expr(void)
{
sf_nodes [sf_level].f_status |= FALL_BIT; /* Never terminates. */
}
void
sf_1for(bool empty_flag)
{
struct flow_node * p;
if (sf_level >= MAX_FLOW) {
warning("Statements nested too deeply\n");
}
else {
p = & sf_nodes [++sf_level];
p -> f_type = K_DO;
p -> f_status = 0;
if (empty_flag) {
p -> f_status |= NULL_FOR_BIT;
}
}
}
void
sf_2for(void)
{
struct flow_node *p;
p = & sf_nodes [sf_level];
sf_level--;
if ( (p -> f_status & BREAK_BIT) ||
(p -> f_status & NULL_FOR_BIT) == 0) {
sf_nodes [sf_level].f_status |= FALL_BIT;
}
else {
sf_nodes [sf_level].f_status &= ~FALL_BIT;
}
}
void
sf_goto(void)
{
/* goto's NEVER fall through, but labels ALWAYS do. */
sf_nodes [sf_level].f_status &= ~FALL_BIT;
}
void
sf_1if(void)
{
struct flow_node * p;
if (sf_level >= MAX_FLOW) {
warning("Statements nested too deeply\n");
}
else {
p = & sf_nodes [++sf_level];
p -> f_type = K_IF;
p -> f_status = 0;
}
}
void
sf_2if(void)
{
struct flow_node * p;
/*
Only set ELSE_BIT if the 'then' clause terminated.
*/
p = & sf_nodes [sf_level];
if ( (p -> f_status & FALL_BIT) == 0) {
p -> f_status |= ELSE_BIT;
}
}
void
sf_3if(void)
{
struct flow_node * p;
/* Both braches must have terminated. */
p = & sf_nodes [sf_level];
sf_level--;
if ( (p -> f_status & ELSE_BIT) == 0 ||
(p -> f_status & BREAK_BIT) ||
(p -> f_status & FALL_BIT)) {
sf_nodes [sf_level].f_status |= FALL_BIT;
}
else {
sf_nodes [sf_level].f_status &= ~FALL_BIT;
}
}
void
sf_label(void)
{
sf_nodes [sf_level].f_status |= FALL_BIT;
}
void
sf_return(void)
{
sf_nodes [sf_level].f_status &= ~FALL_BIT;
}
void
sf_1switch(void)
{
struct flow_node * p;
if (sf_level >= MAX_FLOW) {
warning("Statements nested too deeply\n");
}
else {
p = & sf_nodes [++sf_level];
p -> f_type = K_SWITCH;
p -> f_status = 0;
}
}
void
sf_default(void)
{
sf_nodes [sf_level].f_status |= DEFAULT_BIT;
}
void
sf_2switch(void)
{
struct flow_node * p;
p = & sf_nodes [sf_level];
sf_level--;
if ( (p -> f_status & DEFAULT_BIT) == 0 ||
(p -> f_status & BREAK_BIT) ||
(p -> f_status & FALL_BIT)) {
sf_nodes [sf_level].f_status |= FALL_BIT;
}
else {
sf_nodes [sf_level].f_status &= ~FALL_BIT;
}
}
void
sf_1while(void)
{
struct flow_node * p;
if (sf_level >= MAX_FLOW) {
warning("Statements nested too deeply\n");
}
else {
p = & sf_nodes [++sf_level];
p -> f_type = K_WHILE;
p -> f_status = 0;
}
}
void
sf_2while(void)
{
sf_nodes [--sf_level].f_status |= FALL_BIT; /* Never terminates. */
}
/*
O u t p u t R o u t i n e s.
*/
static char * out_type(en_tokens tok, bool flag);
/*
Disable generation of Sherlock macros, but ONLY if we are not
already generating them!!
This is done by disabling so_entry(), so_?exit() and so_leave().
*/
void
so_disable(void)
{
TICK("so_disable");
/* bug fix: 2/25/89. */
if (fn_gen && fn_enable) {
if (!fn_warn) {
warning("Sherlock macros generated for this function");
}
fn_warn = TRUE;
}
else {
fn_enable = FALSE;
}
}
/* Ouput the cumulative newline count. */
static void
so_cnl(void)
{
int i, count;
count = min(cnl_count, 2);
for (i = 0; i < count; i++) {
sysnlput();
}
cnl_count = 0;
}
/* Output held white space. */
static void
so_hws(void)
{
int i;
for (i = 0; i < hws_count; i++) {
syscput(hws_buf[i]);
}
hws_count = 0;
}
/* Output leading white space. */
static void
so_lws(void)
{
int i;
for (i = 0; i < lws_count; i++) {
syscput(lws_buf[i]);
}
}
/* Output the entry macro. */
void
so_entry(void)
{
char *p;
/* 3/5/89 */
if (m_flag) {
warning("Macro found where entry macro should be");
}
if (!fn_enable || !entry_flag || m_flag || t_inlevel != 0) {
return;
}
TRACEPB("so_entry", printf("(%s)\n", fn_name));
fn_gen = TRUE;
if (last_tok == LCURLY_TOK) {
/* There are no local declarations. */
sysnlput();
so_lws();
}
else if (last_tok == SEMICOLON_TOK) {
/* There ARE local declarations. */
sysnlput();
sysnlput();
so_lws();
}
else {
warning("so_entry: can't happen");
printf("last_tok: %d\n", last_tok);
sysnlput(); sysnlput();
so_lws();
}
/* Special case the main routine. */
if (str_eq(fn_name, "main")) {
syssput(s_init);
syssput("();\n");
so_lws();
syssput(s_parse);
syssput("(argc, argv, \"++\", \"--\");\n\n");
so_lws();
}
if (n_param == 0) {
if (tick_flag) {
syssput(tick);
}
else {
syssput(tickb);
}
syssput("(\"");
syssput(fn_name);
syssput("\");");
}
else {
if (tick_flag) {
syssput(ptrace);
}
else {
syssput(pbtrace);
}
syssput("(\"");
syssput(fn_name);
syssput("\", ");
/* Output the params. */
if (usr_flag) {
so_usr();
}
else {
so_printf();
}
}
/*
Output exactly one blank line unless the function
body is empty (next token is '}' or "return".
Do NOT output a blank line in front of return so that
SDEL will work properly.
*/
p = syshnldel();
if (p == NULL || ( !str_eq(p, "}") && !str_eq(p, "return") )) {
sysnlput();
sysnlput();
}
/* ----- Do NOT use this code!!
if (p != NULL && str_eq(p, "return")) {
sysnlput();
}
else if (p == NULL || !str_eq(p, "}")) {
sysnlput();
sysnlput();
}
----- */
RETURN_VOID("so_entry");
}
/* Output the parameters using the printf function. */
static void
so_printf(void)
{
bool flag;
int i, length, newlength; /* 3/1/89: all this logic. */
char *p;
flag = FALSE;
length = 32 + strlen(fn_name);
/* Output the printf format specification. */
syssput("printf(\"(");
for (i = 0; i < n_param; i++) {
p = out_type(pst[i].p_type, TRUE);
if (p != NULL) {
/* Make sure the line would not be too long. */
length += strlen(p) + 2;
if (length >= 77 && i < n_param-1) {
syssput("\\\n");
length = strlen(p) + 2;
flag = TRUE;
}
/* Output the printf specification. */
syssput(p);
if (i < n_param - 1) {
syssput(", ");
}
}
}
/* End the printf format string. */
syssput(")\\n\", ");
length += 6;
/* Go to the next line if we can't get ALL the params on it. */
for (newlength = length, i = 0; i < n_param; i++) {
newlength += strlen(pst[i].p_name) + 2;
if (pst[i].p_type == K_BOOL) {
newlength += 10; /* strlen("sl_sbout()"); */
}
}
if (newlength >= 77 || flag) {
syssput("\n\t\t");
length = 16;
};
/* Output the list of arguments. */
for (i = 0; i < n_param; i++) {
p = out_type(pst[i].p_type, FALSE);
if (p != NULL) {
/* Compute the new length of the line. */
length += strlen(pst[i].p_name) + 2;
if (pst[i].p_type == K_BOOL) {
length += 10; /* strlen("sl_sbout()"); */
}
/* 6/27/89 */
else if ( pst[i].p_type == K_STRUCT ||
pst[i].p_type == K_UNION
) {
length++;
}
/* Go to a new line if it would be too long. */
if (length >= 77 && i < n_param - 1) {
syssput("\n\t\t");
length = 16;
}
/* 6/27/89 */
if ( pst[i].p_type == K_STRUCT ||
pst[i].p_type == K_UNION
) {
syscput('&');
}
/* 2/27/89 */
if (pst[i].p_type == K_BOOL) {
syssput("sl_sbout(");
syssput(pst[i].p_name);
syssput(")");
}
else {
syssput(pst[i].p_name);
}
if (i < n_param - 1) {
syssput(", ");
}
}
}
syssput("));");
}
static void
so_usr(void)
{
int i;
int length; /* 3/1/89: all this logic. */
syssput(" sl_lpout();\n\t\t");
length = 16;
for (i = 0; i < n_param; i++) {
length += (strlen(pst[i].p_name) + 24);
if (length > 77) {
syssput("\n\t\t");
length = 16 + strlen(pst[i].p_name) + 24;
}
switch(pst[i].p_type) {
case K_CHAR: syssput("sl_cout("); break;
case K_BOOL: syssput("sl_bout("); break;
case K_UNSIGNED: syssput("sl_uiout("); break;
case UNSIGNED_LONG: syssput("sl_ulout("); break;
case K_SIGNED:
case K_ENUM:
case K_SHORT:
case K_INT: syssput("sl_iout("); break;
case K_LONG: syssput("sl_lout("); break;
case STRING_TOK: syssput("sl_sout("); break;
case K_STRUCT:
case K_UNION:
case LPAREN_TOK:
case LBRACK_TOK:
case STAR_TOK: syssput("sl_pout("); break;
case K_DOUBLE:
case K_FLOAT: syssput("sl_fout("); break;
default:
warning("Unknown parameter type: int assumed");
syssput("sl_iout(");
}
/* 6/27/89 */
if (pst[i].p_type == K_STRUCT || pst[i].p_type == K_UNION) {
syscput('&');
}
syssput(pst[i].p_name);
syscput(')');
if (i < n_param - 1) {
/* 2/14/89 */
syssput("; sl_csout(); ");
}
}
/* 2/14/89 */
syssput("; sl_rpout());");
}
static bool old_m;
static bool m_warn;
void
so_1exit(void)
{
/* 2/16/89 */
SL_DISABLE();
if (!fn_enable) {
return;
}
old_m = m_flag;
m_warn = FALSE;
if (m_flag) {
warning("Return inside macro expansion");
m_warn = TRUE;
}
if (!exit_flag || m_flag || old_m || t_inlevel != 0) {
return;
}
TRACEPB("so_1exit", printf("(%s)\n", fn_name));
fn_gen = TRUE;
/* Kill the hold buffer. */
syshkill();
/* Output appropriate white space. */
if (first_tok) {
/* -----
sysnlput();
so_lws();
----- */
so_cnl();
so_lws();
}
else {
so_hws();
}
RETURN_VOID("so_1exit");
}
/* Flag is TRUE if an expression exists. */
void
so_2exit(bool flag)
{
en_tokens type;
/* 2/16/89 */
SL_DISABLE();
/* Don't worry about current macro expansions, only old ones. */
if (!fn_enable || !exit_flag || old_m || t_inlevel != 0) {
return;
}
TRACEPB("so_2exit", printf("%s, flag: %d\n", fn_name, flag));
fn_gen = TRUE;
/* Generate just a return if tick_flag is true. */
if (tick_flag) {
syssput("return");
RETURN_VOID("so_2exit");
}
/*
Generate a warning and RETURN_VOID macro for returns without
expressions in non-void type functions.
*/
if (!flag && fn_type != K_VOID) {
warning("Void return from function of non-void type");
type = K_VOID;
}
else {
type = fn_type;
}
TRACEP("so_2exit", printf("type: %s\n", pr_op(type)));
switch(type) {
case K_VOID: syssput(r_void); break;
case K_CHAR: syssput(r_char); break;
case K_BOOL: syssput(r_bool); break;
case K_UNSIGNED: syssput(r_uint); break; /* bug fix: 2/10/89 */
case UNSIGNED_LONG:
syssput(r_ulong); break; /* bug fix: 2/10/89 */
case K_ENUM:
case K_SIGNED:
case K_SHORT:
case K_INT: syssput(r_int); break;
case K_LONG: syssput(r_long); break;
case STRING_TOK: syssput(r_string); break;
case K_STRUCT:
case K_UNION:
sysnlput(); /* bug fix: 6/27/89 */
so_lws();
syssput(tickx);
break;
case LPAREN_TOK:
case LBRACK_TOK:
case STAR_TOK: syssput(r_ptr); break;
case K_FLOAT: syssput(r_float); break;
case K_DOUBLE: syssput(r_double); break;
default:
warning("Unknown expression type--no RETURN macro generated");
syssput("return");
break;
}
/* Output function name. */
syssput("(\"");
syssput(fn_name);
syscput('"');
/* Structs and unions are handled as follows:
TICKX(function name);
return ...
*/
if (type == K_STRUCT || type == K_UNION) {
syssput(");");
sysnlput();
so_lws();
syssput("return");
}
/*
Output a comma for all types except void, struct or union.
No white space is needed because the white space after
the original "return" will be used.
*/
if (type != K_VOID && type != K_STRUCT && type != K_UNION) {
syscput(',');
}
LEAVE("so_2exit");
}
void
so_3exit(void)
{
/* 2/16/89 */
SL_DISABLE();
if (!fn_enable) {
return;
}
ENTER("so_3exit");
fn_gen = TRUE;
/*
Don't worry about current macro expansions, only old ones.
6/27/89: Don't add anything for struct/union types.
*/
if ( !tick_flag && exit_flag && !old_m && t_inlevel == 0 &&
fn_type != K_STRUCT && fn_type != K_UNION
) {
syscput(')');
}
RETURN_VOID("so_3exit");
}
void
so_leave(void)
{
int i, count;
/* 2/16/89 */
SL_DISABLE();
/* bug fix: 3/5/89 */
if (!fn_enable || tick_flag || !exit_flag || m_flag || t_inlevel != 0) {
return;
}
TRACEPB("so_leave", printf("(%s)\n", fn_name));
fn_gen = TRUE;
/* Examine flow control to see if we need anything. */
if ((sf_nodes [0].f_status & FALL_BIT) == 0) {
RETURN_VOID("so_leave");
}
/* Kill the buffer, containing white space and }. */
syshkill();
/* Output one blank line and leading white space. */
sysnlput();
sysnlput();
so_lws();
/* Output tickx macro */
syssput(tickx);
syssput("(\"");
syssput(fn_name);
syssput("\");");
/* One trailing newline. */
sysnlput();
/* Output the teminating brace of the function. */
syscput('}');
RETURN_VOID("so_leave");
}
static char *
out_type(en_tokens type, bool flag)
{
switch(type) {
case K_CHAR: return "%c";
case K_UNSIGNED: return "%u"; /* bug fix: 2/10/89 */
case UNSIGNED_LONG: return "%lu"; /* bug fix: 2/10/89 */
case K_BOOL: return "%s"; /* 2/27/89: sl_sbout(). */
case K_ENUM:
case K_SIGNED:
case K_SHORT:
case K_INT: return "%d";
case K_LONG: return "%ld";
case STRING_TOK: return "%s";
case K_STRUCT:
case K_UNION:
case LBRACK_TOK:
case LPAREN_TOK:
case STAR_TOK: return "%p";
case K_DOUBLE:
case K_FLOAT: return "%g";
default:
if (flag) {
warn3( "Unknown formal type '",
pr_op(type),
"' int assumed");
}
return "%d";
}
}
static void
sd_dump()
{
SL_DISABLE();
printf("\n");
printf("cur_typedef: %s\n", pr_bool(cur_typedef));
printf("cur_hptype: %s\n", pr_op(cur_hptype));
printf("cur_hftype: %s\n", pr_op(cur_hftype));
printf("cur_ptype: %s\n", pr_op(cur_ptype));
printf("cur_ftype: %s\n", pr_op(cur_ftype));
printf("cur_pid: %s\n", cur_pid);
printf("cur_fid: %s\n", cur_fid);
printf("fn_type: %s\n", pr_op(fn_type));
printf("fn_name: %s\n", fn_name);
printf("\n");
}