installed latest gtac version of sequencer
This commit is contained in:
@@ -1 +1 @@
|
||||
1.6.4
|
||||
1.7.3
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)gen_ss_code.c 1.3 1/16/91
|
||||
@(#)gen_ss_code.c 1.4 4/17/91
|
||||
DESCRIPTION: gen_ss_code.c -- routines to generate state set code
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include "cadef.h"
|
||||
#include "seq.h"
|
||||
|
||||
/*+************************************************************************
|
||||
@@ -28,19 +29,23 @@
|
||||
#define EVENT_STMT 1
|
||||
#define ACTION_STMT 2
|
||||
#define DELAY_STMT 3
|
||||
#define EXIT_STMT 4
|
||||
|
||||
gen_ss_code()
|
||||
{
|
||||
extern LIST ss_list;
|
||||
StateSet *ssp;
|
||||
State *sp;
|
||||
extern Expr *ss_list;
|
||||
Expr *ssp;
|
||||
Expr *sp;
|
||||
|
||||
/* For each state set ... */
|
||||
for (ssp = firstSS(&ss_list); ssp != NULL; ssp = nextSS(ssp))
|
||||
for (ssp = ss_list; ssp != NULL; ssp = ssp->next)
|
||||
{
|
||||
/* For each state ... */
|
||||
for (sp = firstState(&ssp->S_list); sp != NULL; sp = nextState(sp))
|
||||
for (sp = ssp->left; sp != NULL; sp = sp->next)
|
||||
{
|
||||
printf("\f/* Code for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->value, ssp->value);
|
||||
|
||||
/* Generate delay processing function */
|
||||
gen_delay_func(sp, ssp);
|
||||
|
||||
@@ -51,6 +56,9 @@ gen_ss_code()
|
||||
gen_action_func(sp, ssp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate exit handler code */
|
||||
gen_exit_handler();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,44 +67,35 @@ gen_ss_code()
|
||||
state set name and the state name.
|
||||
*/
|
||||
gen_action_func(sp, ssp)
|
||||
State *sp;
|
||||
StateSet *ssp; /* Parent state set */
|
||||
Expr *sp;
|
||||
Expr *ssp; /* Parent state set */
|
||||
{
|
||||
Trans *tp;
|
||||
Action *ap;
|
||||
int trans_num;
|
||||
extern char *prog_name;
|
||||
Expr *tp;
|
||||
Expr *ap;
|
||||
int trans_num;
|
||||
extern char *prog_name;
|
||||
|
||||
printf("\n/* Action function for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->state_name, ssp->ss_name);
|
||||
sp->value, ssp->value);
|
||||
/* action function declaration with ss_ptr as parameter */
|
||||
printf("static a_%s_%s(sprog, ss_ptr)\nSPROG *sprog;\nSSCB\t*ss_ptr;\n{\n",
|
||||
ssp->ss_name, sp->state_name);
|
||||
/* "switch" stmt based on the transition number */
|
||||
printf("static A_%s_%s(sprog, ss_ptr, var_ptr)\n", ssp->value, sp->value);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
/* "switch" statment based on the transition number */
|
||||
printf("\tswitch(ss_ptr->trans_num)\n\t{\n");
|
||||
trans_num = 0;
|
||||
/* For each transition (when statement) ... */
|
||||
for (tp = firstTrans(&sp->T_list); tp != NULL; tp = nextTrans(tp))
|
||||
/* For each transition ("when" statement) ... */
|
||||
for (tp = sp->left; tp != NULL; tp = tp->next)
|
||||
{
|
||||
/* "case" for each transition */
|
||||
printf("\tcase %d:\n", trans_num);
|
||||
/* For each action statement insert action code */
|
||||
for (ap = firstAction(&tp->A_list); ap != NULL;
|
||||
ap = nextAction(ap))
|
||||
for (ap = tp->right; ap != NULL; ap = ap->next)
|
||||
{
|
||||
print_line_num(ap->line_num);
|
||||
switch (ap->type)
|
||||
{
|
||||
case A_STMT:
|
||||
printf("\t\t");
|
||||
/* Evaluate statements */
|
||||
eval_expr(ACTION_STMT, ap->stmt.expr, sp);
|
||||
printf(";\n");
|
||||
break;
|
||||
case A_CCODE:
|
||||
printf("%s\n", ap->stmt.c_code);
|
||||
break;
|
||||
}
|
||||
print_line_num(ap->line_num, ap->src_file);
|
||||
/* Evaluate statements */
|
||||
eval_expr(ACTION_STMT, ap, sp, 2);
|
||||
}
|
||||
/* end of case */
|
||||
printf("\t\treturn;\n");
|
||||
@@ -111,39 +110,39 @@ StateSet *ssp; /* Parent state set */
|
||||
|
||||
/* Generate a C function that checks events for a particular state */
|
||||
gen_event_func(sp, ssp)
|
||||
State *sp;
|
||||
StateSet *ssp;
|
||||
Expr *sp;
|
||||
Expr *ssp;
|
||||
{
|
||||
Trans *tp;
|
||||
int index, trans_num;
|
||||
Expr *tp;
|
||||
int index, trans_num;
|
||||
|
||||
printf("\n/* Event function for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->state_name, ssp->ss_name);
|
||||
printf("static e_%s_%s(sprog, ss_ptr)\n", ssp->ss_name, sp->state_name);
|
||||
sp->value, ssp->value);
|
||||
printf("static E_%s_%s(sprog, ss_ptr, var_ptr)\n", ssp->value, sp->value);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n{\n");
|
||||
printf("SSCB\t*ss_ptr;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
trans_num = 0;
|
||||
sp->ndelay = 0;
|
||||
/* For each transition generate an "if" statement ... */
|
||||
for (tp = firstTrans(&sp->T_list); tp != NULL; tp = nextTrans(tp))
|
||||
for (tp = sp->left; tp != NULL; tp = tp->next)
|
||||
{
|
||||
print_line_num(tp->line_num);
|
||||
print_line_num(tp->line_num, tp->src_file);
|
||||
printf("\tif (");
|
||||
eval_expr(EVENT_STMT, tp->event_expr, sp);
|
||||
eval_expr(EVENT_STMT, tp->left, sp, 0);
|
||||
/* an event triggered, set next state */
|
||||
printf(")\n\t{\n");
|
||||
/* index is the transition number (0, 1, ...) */
|
||||
index = state_block_index_from_name(ssp, tp->new_state_name);
|
||||
index = state_block_index_from_name(ssp, tp->value);
|
||||
if (index < 0)
|
||||
{
|
||||
fprintf(stderr, "Line %d: ", tp->line_num);
|
||||
fprintf(stderr, "No state %s in state set %s\n",
|
||||
tp->new_state_name, ssp->ss_name);
|
||||
tp->value, ssp->value);
|
||||
index = 0; /* default to 1-st state */
|
||||
printf("\t\t/* state %s does not exist */\n",
|
||||
tp->new_state_name);
|
||||
tp->value);
|
||||
}
|
||||
printf("\t\tss_ptr->next_state = ss_ptr->states + %d;\n", index);
|
||||
printf("\t\tss_ptr->next_state = %d;\n", index);
|
||||
printf("\t\tss_ptr->trans_num = %d;\n", trans_num);
|
||||
printf("\t\treturn TRUE;\n\t}\n");
|
||||
trans_num++;
|
||||
@@ -152,89 +151,162 @@ StateSet *ssp;
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
/* Generate delay processing function for a state */
|
||||
gen_delay_func(sp, ssp)
|
||||
State *sp;
|
||||
StateSet *ssp;
|
||||
/* Given a state name and state set struct, find the corresponding
|
||||
state struct and return its index (1-st one is 0) */
|
||||
state_block_index_from_name(ssp, state_name)
|
||||
Expr *ssp;
|
||||
char *state_name;
|
||||
{
|
||||
Trans *tp;
|
||||
Expr *sp;
|
||||
int index;
|
||||
|
||||
printf("\n/* Delay function for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->state_name, ssp->ss_name);
|
||||
printf("static d_%s_%s(sprog, ss_ptr)\n", ssp->ss_name, sp->state_name);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n{\n");
|
||||
sp->ndelay = 0;
|
||||
/* For each transition ... */
|
||||
for (tp = firstTrans(&sp->T_list); tp != NULL; tp = nextTrans(tp))
|
||||
index = 0;
|
||||
for (sp = ssp->left; sp != NULL; sp = sp->next)
|
||||
{
|
||||
print_line_num(tp->line_num);
|
||||
eval_delay(tp->event_expr, sp);
|
||||
if (strcmp(state_name, sp->value) == 0)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
printf("}\n");
|
||||
if (sp->ndelay > ssp->ndelay)
|
||||
ssp->ndelay = sp->ndelay; /* max # delay calls in ss */
|
||||
return;
|
||||
return -1; /* State name non-existant */
|
||||
}
|
||||
|
||||
|
||||
/* Evaluate an expression.
|
||||
Checks for special functions:
|
||||
efSet(ef) and efGet(ef) -> set corresponding bit in ef_mask.
|
||||
pvPut() & pvGet -> replace variable with ptr to db struct.
|
||||
*/
|
||||
eval_expr(stmt_type, ep, sp)
|
||||
int stmt_type; /* EVENT_STMT, ACTION_STMT, or DELAY_STMT */
|
||||
Expr *ep; /* ptr to expression */
|
||||
State *sp; /* ptr to current State struct */
|
||||
/* Generate delay processing function for a state */
|
||||
gen_delay_func(sp, ssp)
|
||||
Expr *sp;
|
||||
Expr *ssp;
|
||||
{
|
||||
Expr *epf;
|
||||
int nparams;
|
||||
Expr *tp;
|
||||
int eval_delay();
|
||||
|
||||
printf("\n/* Delay function for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->value, ssp->value);
|
||||
printf("static D_%s_%s(sprog, ss_ptr, var_ptr)\n", ssp->value, sp->value);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
|
||||
/* For each transition ... */
|
||||
for (tp = sp->left; tp != NULL; tp = tp->next)
|
||||
{
|
||||
print_line_num(tp->line_num, tp->src_file);
|
||||
traverseExprTree(tp, E_FUNC, "delay", eval_delay, sp);
|
||||
}
|
||||
printf("}\n");
|
||||
|
||||
return;
|
||||
}
|
||||
/* Evaluate an expression.
|
||||
*/
|
||||
eval_expr(stmt_type, ep, sp, level)
|
||||
int stmt_type; /* EVENT_STMT, ACTION_STMT, or DELAY_STMT */
|
||||
Expr *ep; /* ptr to expression */
|
||||
Expr *sp; /* ptr to current State struct */
|
||||
int level; /* indentation level */
|
||||
{
|
||||
Expr *epf;
|
||||
int nparams;
|
||||
extern int reent_flag;
|
||||
if (ep == 0)
|
||||
return;
|
||||
|
||||
switch(ep->type)
|
||||
{
|
||||
case E_CMPND:
|
||||
indent(level);
|
||||
printf("{\n");
|
||||
for (epf = ep->left; epf != 0; epf = epf->next)
|
||||
{
|
||||
eval_expr(stmt_type, epf, sp, level+1);
|
||||
}
|
||||
indent(level);
|
||||
printf("}\n");
|
||||
break;
|
||||
case E_STMT:
|
||||
indent(level);
|
||||
eval_expr(stmt_type, ep->left, sp, 0);
|
||||
printf(";\n");
|
||||
break;
|
||||
case E_IF:
|
||||
case E_WHILE:
|
||||
indent(level);
|
||||
if (ep->type == E_IF)
|
||||
printf("if (");
|
||||
else
|
||||
printf("while (");
|
||||
eval_expr(stmt_type, ep->left, sp, 0);
|
||||
printf(")\n");
|
||||
epf = ep->right;
|
||||
if (epf->type == E_CMPND)
|
||||
eval_expr(stmt_type, ep->right, sp, level);
|
||||
else
|
||||
eval_expr(stmt_type, ep->right, sp, level+1);
|
||||
break;
|
||||
case E_ELSE:
|
||||
indent(level);
|
||||
printf("else\n");
|
||||
epf = ep->left;
|
||||
/* Is it "else if" ? */
|
||||
if (epf->type == E_IF || epf->type == E_CMPND)
|
||||
eval_expr(stmt_type, ep->left, sp, level);
|
||||
else
|
||||
eval_expr(stmt_type, ep->left, sp, level+1);
|
||||
break;
|
||||
case E_VAR:
|
||||
printf("%s", ep->value.var->name);
|
||||
if(reent_flag)
|
||||
{ /* Make variables point to allocated structure */
|
||||
Var *vp;
|
||||
vp = (Var *)ep->left;
|
||||
if (vp->type != V_NONE && vp->type != V_EVFLAG)
|
||||
printf("(var_ptr->%s)", ep->value);
|
||||
else
|
||||
printf("%s", ep->value);
|
||||
}
|
||||
else
|
||||
printf("%s", ep->value);
|
||||
break;
|
||||
case E_CONST:
|
||||
printf("%s", ep->value.const);
|
||||
printf("%s", ep->value);
|
||||
break;
|
||||
case E_STRING:
|
||||
printf("\"%s\"", ep->value.const);
|
||||
printf("\"%s\"", ep->value);
|
||||
break;
|
||||
case E_FUNC:
|
||||
if (special_func(stmt_type, ep, sp))
|
||||
break;
|
||||
printf("%s(", ep->value.const);
|
||||
for (epf = ep->right, nparams = 0; epf != 0;
|
||||
printf("%s(", ep->value);
|
||||
for (epf = ep->left, nparams = 0; epf != 0;
|
||||
epf = epf->next, nparams++)
|
||||
{
|
||||
if (nparams > 0)
|
||||
printf(" ,");
|
||||
eval_expr(stmt_type, epf, sp);
|
||||
eval_expr(stmt_type, epf, sp, 0);
|
||||
}
|
||||
printf(") ");
|
||||
break;
|
||||
case E_ASGNOP:
|
||||
case E_BINOP:
|
||||
eval_expr(stmt_type, ep->left, sp);
|
||||
printf("%s", ep->value.const);
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
eval_expr(stmt_type, ep->left, sp, 0);
|
||||
printf(" %s ", ep->value);
|
||||
eval_expr(stmt_type, ep->right, sp, 0);
|
||||
break;
|
||||
case E_PAREN:
|
||||
printf("(");
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
eval_expr(stmt_type, ep->left, sp, 0);
|
||||
printf(")");
|
||||
break;
|
||||
case E_UNOP:
|
||||
printf("%s", ep->value.const);
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
printf("%s", ep->value);
|
||||
eval_expr(stmt_type, ep->left, sp, 0);
|
||||
break;
|
||||
case E_SUBSCR:
|
||||
eval_expr(stmt_type, ep->left, sp);
|
||||
eval_expr(stmt_type, ep->left, sp, 0);
|
||||
printf("[");
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
eval_expr(stmt_type, ep->right, sp, 0);
|
||||
printf("]");
|
||||
break;
|
||||
case E_TEXT:
|
||||
printf("%s\n", ep->left);
|
||||
break;
|
||||
default:
|
||||
if (stmt_type == EVENT_STMT)
|
||||
printf("TRUE"); /* empty event statement defaults to TRUE */
|
||||
@@ -244,45 +316,64 @@ State *sp; /* ptr to current State struct */
|
||||
}
|
||||
}
|
||||
|
||||
enum fcode { F_NONE, F_EFSET, F_EFTEST, F_PVGET, F_PVPUT, F_DELAY };
|
||||
indent(level)
|
||||
int level;
|
||||
{
|
||||
while (level-- > 0)
|
||||
printf("\t");
|
||||
}
|
||||
/* func_name_to_code - convert function name to a code */
|
||||
enum fcode { F_DELAY, F_EFSET, F_EFTEST, F_PVGET, F_PVPUT,
|
||||
F_PVMONITOR, F_PVSTOPMONITOR, F_PVCOUNT, F_PVINDEX,
|
||||
F_PVSTATUS, F_PVSEVERITY, F_PVFLUSH, F_PVERROR, F_PVGETCOMPLETE,
|
||||
F_PVCONNECTED, F_PVCHANNELCOUNT, F_PVCONNECTCOUNT, F_NONE };
|
||||
|
||||
char *fcode_str[] = { "delay", "efSet", "efTest", "pvGet", "pvPut",
|
||||
"pvMonitor", "pvStopMonitor", "pvCount", "pvIndex",
|
||||
"pvStatus", "pvSeverity", "pvFlush", "pvError", "pvGetComplete",
|
||||
"pvConnected", "pvChannelCount", "pvConnectCount", NULL };
|
||||
|
||||
enum fcode func_name_to_code(fname)
|
||||
char *fname;
|
||||
{
|
||||
if (strcmp(fname, "efSet") == 0)
|
||||
return F_EFSET;
|
||||
if (strcmp(fname, "efTest") == 0)
|
||||
return F_EFTEST;
|
||||
if (strcmp(fname, "pvPut") == 0)
|
||||
return F_PVPUT;
|
||||
if (strcmp(fname, "pvGet") == 0)
|
||||
return F_PVGET;
|
||||
if (strcmp(fname, "delay") == 0)
|
||||
return F_DELAY;
|
||||
int i;
|
||||
|
||||
for (i = 0; fcode_str[i] != NULL; i++)
|
||||
{
|
||||
if (strcmp(fname, fcode_str[i]) == 0)
|
||||
return (enum fcode)i;
|
||||
}
|
||||
|
||||
return F_NONE;
|
||||
}
|
||||
|
||||
/* Process special function (returns TRUE if this is a special function) */
|
||||
/* Process special function (returns TRUE if this is a special function)
|
||||
Checks for special functions:
|
||||
efSet(ef) and efGet(ef) -> set corresponding bit in ef_mask.
|
||||
pvPut() & pvGet -> replace variable with ptr to db struct.
|
||||
delay() - replaces delay time with delay index.
|
||||
*/
|
||||
special_func(stmt_type, ep, sp)
|
||||
int stmt_type; /* ACTION_STMT or EVENT_STMT */
|
||||
Expr *ep; /* ptr to function in the expression */
|
||||
State *sp; /* current State struct */
|
||||
int stmt_type; /* ACTION_STMT or EVENT_STMT */
|
||||
Expr *ep; /* ptr to function in the expression */
|
||||
Expr *sp; /* current State struct */
|
||||
{
|
||||
char *fname; /* function name */
|
||||
Expr *ep1; /* 1-st parameter */
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
enum fcode func_code;
|
||||
char *fname; /* function name */
|
||||
Expr *ep1; /* 1-st parameter */
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
enum fcode func_code;
|
||||
int ndelay;
|
||||
|
||||
fname = ep->value.const;
|
||||
fname = ep->value;
|
||||
func_code = func_name_to_code(fname);
|
||||
if (func_code == F_NONE)
|
||||
return FALSE; /* not a special function */
|
||||
|
||||
ep1 = ep->right; /* ptr to 1-st parameters */
|
||||
ep1 = ep->left; /* ptr to 1-st parameters */
|
||||
if ( (ep1 != 0) && (ep1->type == E_VAR) )
|
||||
{
|
||||
vp = ep1->value.var;
|
||||
vp = (Var *)find_var(ep1->value);
|
||||
cp = vp->chan;
|
||||
}
|
||||
else
|
||||
@@ -291,13 +382,15 @@ State *sp; /* current State struct */
|
||||
cp = 0;
|
||||
}
|
||||
|
||||
if (func_code == F_EFSET || func_code == F_EFTEST)
|
||||
switch (func_code)
|
||||
{
|
||||
case F_EFSET:
|
||||
case F_EFTEST:
|
||||
if (vp->type != V_EVFLAG)
|
||||
{
|
||||
fprintf(stderr, "Line %d: ", ep->line_num);
|
||||
fprintf(stderr,
|
||||
"Parameter to efSet() and efTest() must be an event flag\n");
|
||||
"Parameter to \"%s\" must be an event flag\n", fname);
|
||||
}
|
||||
else if (func_code == F_EFSET && stmt_type == EVENT_STMT)
|
||||
{
|
||||
@@ -308,93 +401,83 @@ State *sp; /* current State struct */
|
||||
else
|
||||
{
|
||||
printf("%s(%s)", fname, vp->name);
|
||||
/* OR the ef bit with ef mask in State struct */
|
||||
sp->event_flag_mask |= 1 << (vp->ef_num);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (func_code == F_PVPUT || func_code == F_PVGET)
|
||||
{
|
||||
|
||||
case F_PVPUT:
|
||||
case F_PVGET:
|
||||
case F_PVGETCOMPLETE:
|
||||
case F_PVSTATUS:
|
||||
case F_PVSEVERITY:
|
||||
case F_PVCONNECTED:
|
||||
case F_PVMONITOR:
|
||||
case F_PVSTOPMONITOR:
|
||||
case F_PVCOUNT:
|
||||
case F_PVINDEX:
|
||||
/* DB functions requiring a channel structure */
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "Line %d: ", ep->line_num);
|
||||
fprintf(stderr,
|
||||
"Parameter to pvPut/pvGet must be DB variable.\n");
|
||||
}
|
||||
else if (stmt_type == EVENT_STMT)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"pvPut/pvGet cannot be used as an event.\n");
|
||||
"Parameter to \"%s\" must be DB variable.\n", fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s(%d)", fname, cp->index);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else if (func_code == F_DELAY)
|
||||
{ /* Test for delay: "test_delay(delay_id)" */
|
||||
printf("test_delay(%d)", sp->ndelay++);
|
||||
|
||||
case F_PVFLUSH:
|
||||
case F_PVERROR:
|
||||
case F_PVCHANNELCOUNT:
|
||||
case F_PVCONNECTCOUNT:
|
||||
/* DB functions not requiring a channel structure */
|
||||
printf("%s()", fname);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
|
||||
case F_DELAY:
|
||||
/* Test for delay: "test_delay(delay_id)" */
|
||||
printf("test_delay(%d)", (int)ep->right);
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE; /* not a special function */
|
||||
}
|
||||
|
||||
/* Evaluate delay expression.
|
||||
This is similar to eval_expr() except that all output
|
||||
is supressed until a delay() function is found. All
|
||||
parameters are then processed with eval_expr().
|
||||
*/
|
||||
eval_delay(ep, sp)
|
||||
Expr *ep; /* ptr to expression */
|
||||
State *sp; /* ptr to current State struct */
|
||||
{
|
||||
Expr *epf;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "eval_delay: type=%d\n", ep->type);
|
||||
#endif DEBUG
|
||||
switch(ep->type)
|
||||
{
|
||||
case E_FUNC:
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "fn=%s\n", ep->value.const);
|
||||
#endif DEBUG
|
||||
if (strcmp(ep->value.const, "delay") == 0)
|
||||
{ /* delay function found: replace with special
|
||||
function & parameters, then evaluate 1-st
|
||||
parameter only
|
||||
*/
|
||||
printf("\tstart_delay(%d, ", sp->ndelay++);
|
||||
epf = ep->right; /* paramter */
|
||||
eval_expr(EVENT_STMT, epf, sp);
|
||||
printf(");\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (epf = ep->right; epf != 0; epf = epf->next)
|
||||
{
|
||||
eval_delay(epf, sp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case E_BINOP:
|
||||
eval_delay(ep->left, sp);
|
||||
eval_delay(ep->right, sp);
|
||||
break;
|
||||
case E_PAREN:
|
||||
eval_delay(ep->right, sp);
|
||||
break;
|
||||
case E_UNOP:
|
||||
eval_delay(ep->right, sp);
|
||||
break;
|
||||
case E_SUBSCR:
|
||||
eval_delay(ep->left, sp);
|
||||
eval_delay(ep->right, sp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Evaluate delay expression. */
|
||||
eval_delay(ep, sp)
|
||||
Expr *ep; /* ptr to expression */
|
||||
Expr *sp; /* ptr to current State struct */
|
||||
{
|
||||
Expr *epf;
|
||||
int delay_id;
|
||||
extern char *stype[];
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "eval_delay: type=%s\n", stype[ep->type]);
|
||||
#endif
|
||||
|
||||
delay_id = (int)ep->right;
|
||||
printf("\tstart_delay(%d, ", delay_id);
|
||||
|
||||
/* Output each parameter */
|
||||
eval_expr(EVENT_STMT, ep->left, sp, 0);
|
||||
|
||||
printf(");\n");
|
||||
}
|
||||
/* Generate exit handler code */
|
||||
gen_exit_handler()
|
||||
{
|
||||
extern Expr *exit_code_list;
|
||||
Expr *ep;
|
||||
|
||||
printf("/* Exit handler */\n");
|
||||
printf("static exit_handler(sprog, var_ptr)\n");
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
for (ep = exit_code_list; ep != 0; ep = ep->next)
|
||||
{
|
||||
eval_expr(EXIT_STMT, ep, 0, 1);
|
||||
}
|
||||
printf("}\n\n");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
@(#)gen_tables.c 1.1 5/30/91
|
||||
DESCRIPTION: Generate tables for run-time sequencer.
|
||||
See also: phase2.c & gen_ss_code.c
|
||||
ENVIRONMENT: UNIX
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* #define DEBUG 1 */
|
||||
/*#define DEBUG 1*/
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)parse.c 1.1 10/16/90
|
||||
@(#)parse.c 1.3 5/1/91
|
||||
DESCRIPTION: Parsing support routines for state notation compiler.
|
||||
The 'yacc' parser calls these routines to build the tables
|
||||
and linked lists, which are then passed on to the phase 2 routines.
|
||||
@@ -26,27 +26,21 @@
|
||||
|
||||
int debug_print_flag = 0; /* Debug level (set by source file) */
|
||||
|
||||
int line_num; /* Current line number */
|
||||
|
||||
char *prog_name; /* ptr to program name (string) */
|
||||
|
||||
char *prog_param; /* parameter string for program stmt */
|
||||
|
||||
LIST defn_c_list; /* definition C code */
|
||||
Expr *defn_c_list; /* definition C code list */
|
||||
|
||||
LIST ss_list; /* start of state-set list */
|
||||
Expr *ss_list; /* Start of state set list */
|
||||
|
||||
Expr *exit_code_list; /* Start of exit code list */
|
||||
|
||||
LIST var_list; /* start of variable list */
|
||||
|
||||
LIST chan_list; /* start of DB channel list */
|
||||
|
||||
LIST state_list; /* temporary state list */
|
||||
|
||||
LIST action_list; /* temporary action list */
|
||||
|
||||
LIST trans_list; /* temporary transition list */
|
||||
|
||||
char *global_c_code; /* global C code following state program */
|
||||
Expr *global_c_list; /* global C code following state program */
|
||||
/*+************************************************************************
|
||||
* NAME: snc_init
|
||||
*
|
||||
@@ -60,13 +54,11 @@ char *global_c_code; /* global C code following state program */
|
||||
*-*************************************************************************/
|
||||
init_snc()
|
||||
{
|
||||
lstInit(&defn_c_list);
|
||||
lstInit(&ss_list);
|
||||
extern char in_file[], *src_file;
|
||||
|
||||
lstInit(&var_list);
|
||||
lstInit(&chan_list);
|
||||
lstInit(&state_list);
|
||||
lstInit(&action_list);
|
||||
lstInit(&trans_list);
|
||||
src_file = &in_file[0];
|
||||
return;
|
||||
}
|
||||
/*+************************************************************************
|
||||
@@ -90,7 +82,7 @@ char *pname, *pparam;
|
||||
prog_name = pname;
|
||||
prog_param = pparam;
|
||||
#ifdef DEBUG
|
||||
printf("program name = %s\n", prog_name);
|
||||
fprintf(stderr, "program name = %s\n", prog_name);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -102,13 +94,14 @@ char *name; /* ptr to variable name */
|
||||
char *s_length; /* array lth (NULL=single element) */
|
||||
char *value; /* initial value or NULL */
|
||||
{
|
||||
Var *vp;
|
||||
int length;
|
||||
Var *vp;
|
||||
int length;
|
||||
extern int line_num;
|
||||
|
||||
if (s_length == 0)
|
||||
length = 0;
|
||||
else if (type == V_STRING)
|
||||
length = MAX_STRING_SIZE;
|
||||
length = 0;
|
||||
else
|
||||
{
|
||||
length = atoi(s_length);
|
||||
@@ -116,7 +109,7 @@ char *value; /* initial value or NULL */
|
||||
length = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("variable decl: type=%d, name=%s, length=%d\n", type, name, length);
|
||||
fprintf(stderr, "variable decl: type=%d, name=%s, length=%d\n", type, name, length);
|
||||
#endif
|
||||
/* See if variable already declared */
|
||||
vp = (Var *)find_var(name);
|
||||
@@ -138,15 +131,13 @@ char *value; /* initial value or NULL */
|
||||
|
||||
/* "Assign" statement: assign a variable to a DB channel.
|
||||
elem_num is ignored in this version) */
|
||||
assign_stmt(name, lower_lim, upper_lim, db_name)
|
||||
assign_stmt(name, db_name)
|
||||
char *name; /* ptr to variable name */
|
||||
char *lower_lim; /* ptr to lower array limit */
|
||||
char *upper_lim; /* ptr to upper array limit */
|
||||
char *db_name; /* ptr to db name */
|
||||
{
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
int range_low, range_high, length;
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
extern int line_num;
|
||||
|
||||
/* Find the variable */
|
||||
vp = (Var *)find_var(name);
|
||||
@@ -163,53 +154,27 @@ char *db_name; /* ptr to db name */
|
||||
cp->var = vp; /* make connection to variable */
|
||||
vp->chan = cp; /* reverse ptr */
|
||||
cp->db_name = db_name; /* DB name */
|
||||
cp->count = vp->length; /* default count is variable length */
|
||||
|
||||
/* convert specified range REMOVED********* */
|
||||
length = vp->length;
|
||||
if (length == 0)
|
||||
length = 1; /* not an array */
|
||||
if (vp->type == V_STRING)
|
||||
length = 1; /* db treats strings as length 1 */
|
||||
cp->length = length;
|
||||
cp->offset = 0;
|
||||
cp->mon_flag = FALSE; /* assume no monitor */
|
||||
cp->ef_var = NULL; /* assume no sync event flag */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build the range string, e.g. "0", and "9" into "0,9" */
|
||||
char *
|
||||
range(low, high)
|
||||
char *low, *high;
|
||||
{
|
||||
static char range_str[30];
|
||||
sprintf(range_str, "%s,%s", low, high);
|
||||
return range_str;
|
||||
}
|
||||
|
||||
|
||||
/* Parsing a "monitor" statement */
|
||||
monitor_stmt(name, offset, delta)
|
||||
monitor_stmt(name, delta)
|
||||
char *name; /* variable name (should be assigned) */
|
||||
char *offset; /* array offset */
|
||||
char *delta; /* monitor delta */
|
||||
{
|
||||
Chan *cp;
|
||||
int offs;
|
||||
extern int line_num;
|
||||
|
||||
/* Pick up array offset */
|
||||
if (offset == 0)
|
||||
offs = 0;
|
||||
else
|
||||
offs = atoi(offset);
|
||||
if (offs < 0)
|
||||
offs = 0;
|
||||
/* Find a channel assigned to this variable */
|
||||
cp = (Chan *)find_chan(name, offs);
|
||||
cp = (Chan *)find_chan(name);
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "monitor: variable %s[%s] not assigned, line %d\n",
|
||||
name, offset, line_num);
|
||||
fprintf(stderr, "monitor: variable %s not assigned, line %d\n",
|
||||
name, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -220,29 +185,22 @@ char *delta; /* monitor delta */
|
||||
}
|
||||
|
||||
/* Parsing "sync" statement */
|
||||
sync_stmt(name, offset, ef_name)
|
||||
sync_stmt(name, ef_name)
|
||||
char *name;
|
||||
char *offset;
|
||||
char *ef_name;
|
||||
{
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
int offs;
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
extern int line_num;
|
||||
|
||||
/* Find the variable */
|
||||
if (offset == 0)
|
||||
offs = 0;
|
||||
else
|
||||
offs = atoi(offset);
|
||||
if (offs < 0)
|
||||
offs = 0;
|
||||
cp = (Chan *)find_chan(name, offs);
|
||||
cp = (Chan *)find_chan(name);
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "sync: variable %s[%s] not assigned, line %d\n",
|
||||
name, offset, line_num);
|
||||
fprintf(stderr, "sync: variable %s not assigned, line %d\n",
|
||||
name, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the event flag varible */
|
||||
vp = (Var *)find_var(ef_name);
|
||||
if (vp == 0 || vp->type != V_EVFLAG)
|
||||
@@ -251,142 +209,41 @@ char *ef_name;
|
||||
ef_name, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert pointers between Var & Chan structures */
|
||||
cp->ef_var = vp;
|
||||
vp->chan = cp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Definition C code */
|
||||
defn_c_stmt(c_str)
|
||||
char *c_str;
|
||||
char *c_str; /* ptr to C code string */
|
||||
{
|
||||
Action *ap;
|
||||
Expr *ep;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("defn_c_stmt\n");
|
||||
fprintf(stderr, "defn_c_stmt\n");
|
||||
#endif
|
||||
ap = allocAction();
|
||||
lstAdd(&defn_c_list, (NODE *)ap);
|
||||
ap->type = A_CCODE;
|
||||
ap->stmt.c_code = c_str;
|
||||
ap->line_num = line_num;
|
||||
ep = expression(E_TEXT, "", c_str, 0);
|
||||
if (defn_c_list == 0)
|
||||
defn_c_list = ep;
|
||||
else
|
||||
link_expr(defn_c_list, ep);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parsing "ss" statement */
|
||||
state_set(ss_name)
|
||||
char *ss_name;
|
||||
/* Global C code (follows state program) */
|
||||
global_c_stmt(c_str)
|
||||
char *c_str; /* ptr to C code */
|
||||
{
|
||||
StateSet *ssp;
|
||||
|
||||
# ifdef DEBUG
|
||||
printf("state_set: ss_name=%s\n", ss_name);
|
||||
#endif
|
||||
/* Is this state set already declared ? */
|
||||
if (find_state_set(ss_name) != NULL)
|
||||
{
|
||||
fprintf(stderr, "Duplicate state set name: %s, line %d\n",
|
||||
ss_name, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
/* create and fill in state-set block */
|
||||
ssp = allocSS();
|
||||
lstAdd(&ss_list, (NODE *)ssp);
|
||||
ssp->ss_name = ss_name;
|
||||
/* move temporary state list into this node */
|
||||
#ifdef DEBUG
|
||||
printf(" # states = %d\n", lstCount(&state_list));
|
||||
#endif DEBUG
|
||||
ssp->S_list = state_list;
|
||||
lstInit(&state_list);
|
||||
global_c_list = expression(E_TEXT, "", c_str, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
state_block(state_name)
|
||||
char *state_name;
|
||||
{
|
||||
State *sp;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("state_block: state_name=%s\n", state_name);
|
||||
#endif
|
||||
sp = firstState(&state_list);
|
||||
if (find_state(state_name, sp) != NULL)
|
||||
{
|
||||
fprintf(stderr, "Duplicate state name: %s, line %d\n",
|
||||
state_name, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
sp = allocState();
|
||||
lstAdd(&state_list, (NODE *)sp);
|
||||
sp->state_name = state_name;
|
||||
/* move tmp transition list into this node */
|
||||
sp->T_list = trans_list;
|
||||
lstInit(&trans_list);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parsing transition part of "when" clause */
|
||||
transition(new_state_name, event_expr)
|
||||
char *new_state_name;
|
||||
Expr *event_expr; /* event expression */
|
||||
{
|
||||
Trans *tp;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("transition: new_state_name=%s\n", new_state_name);
|
||||
#endif
|
||||
tp = allocTrans();
|
||||
lstAdd(&trans_list, (NODE *)tp);
|
||||
tp->new_state_name = new_state_name;
|
||||
tp->line_num = line_num;
|
||||
/* move tmp action list into this node */
|
||||
tp->A_list = action_list;
|
||||
tp->event_expr = event_expr;
|
||||
lstInit(&action_list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Action statement (lvalue = expression;) or (function())*/
|
||||
action_stmt(ep)
|
||||
Expr *ep; /* ptr to expression */
|
||||
{
|
||||
Action *ap;
|
||||
#ifdef DEBUG
|
||||
printf("action_function\n");
|
||||
#endif
|
||||
ap = allocAction();
|
||||
lstAdd(&action_list, (NODE *)ap);
|
||||
ap->type = A_STMT;
|
||||
ap->stmt.expr = ep;
|
||||
ap->line_num = line_num;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Action statement: in-line C code */
|
||||
action_c_stmt(c_str)
|
||||
char *c_str;
|
||||
{
|
||||
Action *ap;
|
||||
#ifdef DEBUG
|
||||
printf("action_c_stmt\n");
|
||||
#endif
|
||||
ap = allocAction();
|
||||
lstAdd(&action_list, (NODE *)ap);
|
||||
ap->type = A_CCODE;
|
||||
ap->stmt.c_code = c_str;
|
||||
ap->line_num = line_num;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Find a variable by name; returns a pointer to the Var struct;
|
||||
returns 0 if the variable is not found. */
|
||||
find_var(name)
|
||||
@@ -395,7 +252,7 @@ char *name;
|
||||
Var *vp;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("find_var, name=%s: ", name);
|
||||
fprintf(stderr, "find_var, name=%s: ", name);
|
||||
#endif
|
||||
vp = firstVar(&var_list);
|
||||
while (vp != NULL)
|
||||
@@ -403,38 +260,31 @@ char *name;
|
||||
if (strcmp(vp->name, name) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("found\n");
|
||||
fprintf(stderr, "found\n");
|
||||
#endif
|
||||
return (int)vp;
|
||||
}
|
||||
vp = nextVar(vp);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("not found\n");
|
||||
fprintf(stderr, "not found\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find channel with same variable name and same offset */
|
||||
find_chan(name, offset)
|
||||
find_chan(name)
|
||||
char *name; /* variable name */
|
||||
int offset;/* array offset */
|
||||
{
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
int chan_offs;
|
||||
|
||||
if (offset < 0)
|
||||
offset = 0;
|
||||
for (cp = firstChan(&chan_list); cp != NULL; cp = nextChan(cp))
|
||||
{
|
||||
vp = cp->var;
|
||||
if (vp == 0)
|
||||
continue;
|
||||
chan_offs = cp->offset;
|
||||
if (chan_offs < 0)
|
||||
chan_offs = 0;
|
||||
if (strcmp(vp->name, name) == 0 && chan_offs == offset)
|
||||
if (strcmp(vp->name, name) == 0)
|
||||
{
|
||||
return (int)cp;
|
||||
}
|
||||
@@ -442,34 +292,6 @@ int offset;/* array offset */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given the name of a state, find ptr to the state struct */
|
||||
find_state(state_name, sp)
|
||||
char *state_name; /* state name we're looking for */
|
||||
State *sp; /* start of state list */
|
||||
{
|
||||
for (; sp != NULL; sp = nextState(sp))
|
||||
{
|
||||
if (strcmp(sp->state_name, state_name) == 0)
|
||||
return (int)sp;
|
||||
}
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
/* Given the name of a state set, find ptr to state set struc */
|
||||
find_state_set(ss_name)
|
||||
char *ss_name; /* state set name we're looking for */
|
||||
{
|
||||
StateSet *ssp;
|
||||
extern LIST ss_list;
|
||||
|
||||
for (ssp = firstSS(&ss_list); ssp != NULL; ssp = nextSS(ssp))
|
||||
{
|
||||
if (strcmp(ssp->ss_name, ss_name) == 0)
|
||||
return (int)ssp;
|
||||
}
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
/* Set debug print flag */
|
||||
set_debug_print(flag)
|
||||
char *flag;
|
||||
@@ -478,117 +300,114 @@ char *flag;
|
||||
}
|
||||
|
||||
/* Parsing "program" statement */
|
||||
program(c_code)
|
||||
char *c_code;
|
||||
program(prog_list)
|
||||
Expr *prog_list;
|
||||
{
|
||||
global_c_code = c_code;
|
||||
phase2();
|
||||
ss_list = prog_list;
|
||||
#ifdef DEBUG
|
||||
print_struct(ss_list);
|
||||
#endif
|
||||
phase2(ss_list);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Build an expression list (hierarchical) */
|
||||
Expr *expression(type, value, left, right)
|
||||
int type;
|
||||
char *value;
|
||||
Expr *left, *right;
|
||||
/* Exit code */
|
||||
exit_code(ep)
|
||||
Expr *ep;
|
||||
{
|
||||
Expr *ep;
|
||||
exit_code_list = ep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* alloc a block for this item or expression */
|
||||
/* Build an expression list (hierarchical):
|
||||
Builds a node on a binary tree for each expression primitive.
|
||||
*/
|
||||
Expr *expression(type, value, left, right)
|
||||
int type; /* E_BINOP, E_ASGNOP, etc */
|
||||
char *value; /* "==", "+=", var name, contstant, etc. */
|
||||
Expr *left; /* LH side */
|
||||
Expr *right; /* RH side */
|
||||
{
|
||||
Expr *ep;
|
||||
extern int line_num, c_line_num;
|
||||
extern char *src_file;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "expression: type=%d, value=%s, left=%d, right=%d\n",
|
||||
type, value, left, right);
|
||||
extern char *stype[];
|
||||
#endif
|
||||
/* Allocate a structure for this item or expression */
|
||||
ep = allocExpr();
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "expression: ep=%d, type=%s, value=\"%s\", left=%d, right=%d\n",
|
||||
ep, stype[type], value, left, right);
|
||||
#endif
|
||||
/* Fill in the structure */
|
||||
ep->next = (Expr *)0;
|
||||
ep->last = ep;
|
||||
ep->type = type;
|
||||
ep->value.const = value;
|
||||
ep->value = value;
|
||||
ep->left = left;
|
||||
ep->right = right;
|
||||
ep->line_num = line_num;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case E_VAR: /* variable or pre-defined constant */
|
||||
if (pre_defined_const(ep))
|
||||
{
|
||||
ep->type = E_CONST;
|
||||
break; /* defined constant */
|
||||
}
|
||||
/* find the variable */
|
||||
ep->value.var = (Var *)find_var(value);
|
||||
if (ep->value.var == 0)
|
||||
{
|
||||
fprintf(stderr, "variable \"%s\" not declared, line no. %d\n",
|
||||
value, ep->line_num);
|
||||
}
|
||||
break;
|
||||
|
||||
case E_CONST: /* number const */
|
||||
break;
|
||||
|
||||
case E_STRING: /* string const */
|
||||
break;
|
||||
|
||||
case E_BINOP: /* binary op. ( left_expr OP rt_expr ) */
|
||||
break;
|
||||
|
||||
case E_UNOP: /* unary op. */
|
||||
break;
|
||||
|
||||
case E_PAREN: /* parenthetical expr. */
|
||||
break;
|
||||
|
||||
case E_FUNC:
|
||||
break;
|
||||
|
||||
case E_EMPTY: /* empty */
|
||||
break;
|
||||
|
||||
case E_SUBSCR: /* subscript */
|
||||
break;
|
||||
|
||||
default: /* any other */
|
||||
fprintf(stderr, "? %d: %s, line no. %d\n", type, value, line_num);
|
||||
break;
|
||||
}
|
||||
if (type == E_TEXT)
|
||||
ep->line_num = c_line_num;
|
||||
else
|
||||
ep->line_num = line_num;
|
||||
ep->src_file = src_file;
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
/* Check for defined constant */
|
||||
pre_defined_const(ep)
|
||||
Expr *ep;
|
||||
/* Link two expression structures and/or lists. Returns ptr to combined list.
|
||||
Note: ->last ptrs are correct only for 1-st and last structures in the list */
|
||||
Expr *link_expr(ep1, ep2)
|
||||
Expr *ep1; /* beginning of 1-st structure or list */
|
||||
Expr *ep2; /* beginning 2-nd (append it to 1-st) */
|
||||
{
|
||||
if ( (strcmp(ep->value.const, "TRUE") == 0)
|
||||
|| (strcmp(ep->value.const, "FALSE") == 0) )
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
Expr *ep;
|
||||
|
||||
/* Add a parameter (expression) to end of list */
|
||||
Expr *parameter(ep, p_list)
|
||||
Expr *ep;
|
||||
Expr *p_list; /* current list */
|
||||
{
|
||||
Expr *ep1;
|
||||
if (ep1 == 0)
|
||||
return ep2; /* shouldn't happen */
|
||||
else if (ep2 == 0)
|
||||
return ep1;
|
||||
|
||||
ep->next = 0;
|
||||
if (p_list == 0)
|
||||
return ep;
|
||||
|
||||
ep1 = p_list;
|
||||
while (ep1->next != 0)
|
||||
ep1 = ep1->next;
|
||||
ep1->next = ep;
|
||||
return p_list;
|
||||
(ep1->last)->next = ep2;
|
||||
ep1->last = ep2->last;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "link_expr(");
|
||||
for (ep = ep1; ; ep = ep->next)
|
||||
{
|
||||
fprintf(stderr, "%d, ", ep);
|
||||
if (ep == ep1->last)
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, ")\n");
|
||||
#endif DEBUG
|
||||
return ep1;
|
||||
}
|
||||
|
||||
/*#define PHASE2*/
|
||||
/* Interpret pre-processor code */
|
||||
pp_code(line, fname)
|
||||
char *line;
|
||||
char *fname;
|
||||
{
|
||||
extern int line_num;
|
||||
|
||||
line_num = atoi(line);
|
||||
src_file = fname;
|
||||
}
|
||||
|
||||
char *stype[] = {
|
||||
"E_EMPTY", "E_CONST", "E_VAR", "E_FUNC", "E_STRING", "E_UNOP", "E_BINOP",
|
||||
"E_ASGNOP", "E_PAREN", "E_SUBSCR", "E_TEXT", "E_STMT", "E_CMPND",
|
||||
"E_IF", "E_ELSE", "E_WHILE", "E_SS", "E_STATE", "E_WHEN" };
|
||||
|
||||
/* #define PHASE2*/
|
||||
#ifdef PHASE2
|
||||
phase2()
|
||||
phase2(ss_list)
|
||||
Expr *ss_list;
|
||||
{
|
||||
fprintf(stderr, "phase2() - dummy\07\n");
|
||||
/* Print structures */
|
||||
print_struct(ss_list);
|
||||
}
|
||||
#endif PHASE2
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1989, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)parse.h 1.1 10/16/90
|
||||
@(#)parse.h 1.2 4/17/91
|
||||
DESCRIPTION: Structures for parsing the state notation language.
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
@@ -15,63 +15,19 @@
|
||||
|
||||
#include "lstLib.h" /* VxWorks "list" routines & definitions */
|
||||
|
||||
struct state_set /* state-set block */
|
||||
{
|
||||
NODE SS_link; /* link to next state set block */
|
||||
char *ss_name; /* state set name */
|
||||
LIST S_list; /* link to first state block */
|
||||
int ndelay; /* Max # delay calls in state set */
|
||||
};
|
||||
typedef struct state_set StateSet;
|
||||
|
||||
struct state /* State block */
|
||||
{
|
||||
NODE S_link; /* link to next state in this SS */
|
||||
char *state_name; /* state name */
|
||||
int event_flag_mask; /* event flag mask for this state */
|
||||
int ndelay; /* # delay calls */
|
||||
LIST T_list; /* start of transition list */
|
||||
};
|
||||
typedef struct state State;
|
||||
|
||||
struct trans /* Transition Block */
|
||||
{
|
||||
NODE T_link; /* link to next transition block */
|
||||
int trans_num; /* transition number */
|
||||
int line_num;
|
||||
char *new_state_name; /* new state name */
|
||||
struct expression *event_expr; /* event expression */
|
||||
LIST A_list; /* start of action list */
|
||||
};
|
||||
typedef struct trans Trans;
|
||||
|
||||
struct expression /* Expression block */
|
||||
{
|
||||
struct expression *next; /* link to next expression */
|
||||
struct expression *last; /* link to last in list */
|
||||
struct expression *left; /* ptr to left expression */
|
||||
struct expression *right; /* ptr to right expression */
|
||||
int type; /* operator or expression type */
|
||||
union { /* for variables, functions, & constants */
|
||||
struct var *var; /* ptr to variable definition */
|
||||
char *name; /* ptr to function name */
|
||||
char *const; /* ptr to constant */
|
||||
} value;
|
||||
int type; /* expression type (E_*) */
|
||||
char *value; /* operator or value string */
|
||||
int line_num; /* line number */
|
||||
char *src_file; /* effective source file */
|
||||
};
|
||||
typedef struct expression Expr;
|
||||
|
||||
struct action /* Action block */
|
||||
{
|
||||
NODE A_link; /* link to next action (or NULL) */
|
||||
int line_num; /* line number of statement */
|
||||
int type; /* A_CCODE, A_FUNC, A_STMT */
|
||||
union stmt {
|
||||
Expr *expr; /* ptr to expression (A_STMT) */
|
||||
char *c_code; /* ptr to imbedded C code (A_CCODE) */
|
||||
} stmt;
|
||||
};
|
||||
typedef struct action Action;
|
||||
|
||||
struct var /* Variable or function definition */
|
||||
{
|
||||
NODE V_link; /* next variable in list */
|
||||
@@ -87,62 +43,63 @@ typedef struct var Var;
|
||||
struct db_chan /* DB channel */
|
||||
{
|
||||
NODE D_link; /* next db chan in list */
|
||||
char *db_name; /* db name if assigned */
|
||||
char *db_name; /* database name */
|
||||
int index; /* channel array index */
|
||||
Var *var; /* ptr to variable definition */
|
||||
int offset; /* array offset (normally 0) */
|
||||
int length; /* sub-array length */
|
||||
Var *ef_var; /* ptr to event flag variable for sync */
|
||||
int count; /* count for db access */
|
||||
int mon_flag; /* TRUE if channel is "monitored" */
|
||||
float delta; /* monitor dead-band */
|
||||
float timeout; /* monitor timeout (seconds) */
|
||||
Var *ef_var; /* ptr to event flag variable for sync */
|
||||
float timeout; /* monitor timeout */
|
||||
};
|
||||
typedef struct db_chan Chan;
|
||||
|
||||
Expr *expression(), *link_expr();
|
||||
|
||||
/* Linked list definitions to get rid of yucky in-line code */
|
||||
#define nextSS(node) (StateSet *)lstNext( (NODE *)node )
|
||||
#define firstSS(head) (StateSet *)lstFirst( (LIST *)head )
|
||||
#define allocSS() (StateSet *)malloc(sizeof(StateSet));
|
||||
#define nextState(node) (State *)lstNext( (NODE *)node )
|
||||
#define firstState(head) (State *)lstFirst( (LIST *)head )
|
||||
#define allocState() (State *)malloc(sizeof(State));
|
||||
#define nextTrans(node) (Trans *)lstNext( (NODE *)node )
|
||||
#define firstTrans(head) (Trans *)lstFirst( (LIST *)head )
|
||||
#define allocTrans() (Trans *)malloc(sizeof(Trans));
|
||||
#define allocExpr() (Expr *)malloc(sizeof(Expr));
|
||||
#define nextAction(node) (Action *)lstNext( (NODE *)node )
|
||||
#define firstAction(head) (Action *)lstFirst( (LIST *)head )
|
||||
#define allocAction() (Action *)malloc(sizeof(Action));
|
||||
#define nextVar(node) (Var *)lstNext( (NODE *)node )
|
||||
|
||||
#define allocVar() (Var *)malloc(sizeof(Var));
|
||||
#define nextVar(node) (Var *)lstNext( (NODE *)node )
|
||||
#define firstVar(head) (Var *)lstFirst( (LIST *)head )
|
||||
|
||||
#define allocChan() (Chan *)malloc(sizeof(Chan));
|
||||
#define nextChan(node) (Chan *)lstNext( (NODE *)node )
|
||||
#define firstChan(head) (Chan *)lstFirst( (LIST *)head )
|
||||
#define allocChan() (Chan *)malloc(sizeof(Chan));
|
||||
|
||||
/* Variable types */
|
||||
#define V_NONE 0 /* not defined */
|
||||
#define V_FLOAT 1 /* float */
|
||||
#define V_INT 2 /* int */
|
||||
#define V_SHORT 3 /* short */
|
||||
#define V_CHAR 4 /* char */
|
||||
#define V_DOUBLE 5 /* double */
|
||||
#define V_STRING 6 /* strings (array of char) */
|
||||
#define V_EVFLAG 7 /* event flag */
|
||||
#define V_FUNC 8 /* function (not a variable) */
|
||||
#define V_CHAR 1 /* char */
|
||||
#define V_SHORT 2 /* short */
|
||||
#define V_INT 3 /* int (but converted to long) */
|
||||
#define V_LONG 4 /* long */
|
||||
#define V_FLOAT 5 /* float */
|
||||
#define V_DOUBLE 6 /* double */
|
||||
#define V_STRING 7 /* strings (array of char) */
|
||||
#define V_EVFLAG 8 /* event flag */
|
||||
#define V_FUNC 9 /* function (not a variable) */
|
||||
#define V_UCHAR 11 /* unsigned char */
|
||||
#define V_USHORT 12 /* unsigned short */
|
||||
#define V_UINT 13 /* unsigned int (converted to unsigned long) */
|
||||
#define V_ULONG 14 /* unsigned long */
|
||||
|
||||
/* Expression type */
|
||||
/* Expression types */
|
||||
#define E_EMPTY 0 /* empty expression */
|
||||
#define E_CONST 1 /* numeric constant */
|
||||
#define E_VAR 2 /* variable */
|
||||
#define E_FUNC 3 /* function */
|
||||
#define E_STR 4 /* ptr to string consatant */
|
||||
#define E_STRING 4 /* ptr to string consatant */
|
||||
#define E_UNOP 5 /* unary operator: OP expr (-, +, or !) */
|
||||
#define E_BINOP 6 /* binary operator: expr OP expr */
|
||||
#define E_PAREN 7 /* parenthesis around expression */
|
||||
#define E_SUBSCR 8 /* subscript */
|
||||
#define E_STRING 9 /* string const */
|
||||
#define E_EMPTY 0 /* empty expression */
|
||||
|
||||
/* Action types */
|
||||
#define A_CCODE 1 /* imbedded C code: %% or %{...}% */
|
||||
#define A_STMT 2 /* lvalue = expression; or function();*/
|
||||
#define E_ASGNOP 7 /* assign operatro: (=, +=, *=, etc.) */
|
||||
#define E_PAREN 8 /* parenthesis around an expression */
|
||||
#define E_SUBSCR 9 /* subscript */
|
||||
#define E_TEXT 10 /* C code or other text to be inserted */
|
||||
#define E_STMT 11 /* simple statement */
|
||||
#define E_CMPND 12 /* begin compound statement: {...} */
|
||||
#define E_IF 13 /* if statement */
|
||||
#define E_ELSE 14 /* if statement */
|
||||
#define E_WHILE 15 /* while statement */
|
||||
#define E_SS 16 /* state set statement */
|
||||
#define E_STATE 17 /* state statement */
|
||||
#define E_WHEN 18 /* when statement */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)phase2.c 1.4 1/16/91
|
||||
@(#)phase2.c 1.5 4/17/91
|
||||
DESCRIPTION: Phase 2 code generation routines for SNC.
|
||||
Produces code and tables in C output file.
|
||||
See also: gen_ss_code.c
|
||||
@@ -13,8 +13,12 @@
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include "seq.h"
|
||||
|
||||
/*+************************************************************************
|
||||
|
||||
int num_channels = 0; /* number of db channels */
|
||||
int num_ss = 0; /* number of state sets */
|
||||
int num_errors = 0; /* number of errors detected in phase 2 processing */
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: phase2
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
@@ -27,22 +31,21 @@
|
||||
*
|
||||
* NOTES: All inputs are external globals.
|
||||
*-*************************************************************************/
|
||||
int num_vars = 0; /* number of variables declared */
|
||||
int num_channels = 0; /* number of db channels */
|
||||
int num_ss = 0; /* number of state sets */
|
||||
int num_errors = 0; /* number of errors detected in phase 2 processing */
|
||||
|
||||
phase2()
|
||||
{
|
||||
extern LIST var_list; /* variables (from parse) */
|
||||
extern LIST ss_list; /* state sets (from parse) */
|
||||
extern char *prog_name; /* program name (from parse) */
|
||||
extern char *global_c_code; /* global C code */
|
||||
extern Expr *ss_list; /* state sets (from parse) */
|
||||
extern Expr *global_c_list; /* global C code */
|
||||
|
||||
/* Count number of variables, db channels, and state sets defined */
|
||||
num_vars = lstCount((NODE *)&var_list);
|
||||
/* Count number of db channels and state sets defined */
|
||||
num_channels = db_chan_count();
|
||||
num_ss = lstCount((NODE *)&ss_list);
|
||||
num_ss = exprCount(ss_list);
|
||||
|
||||
/* Reconcile all variable and tie each to the appropriate VAR struct */
|
||||
reconcile_variables();
|
||||
|
||||
/* reconcile all state names, including next state in transitions */
|
||||
reconcile_states();
|
||||
|
||||
/* Generate preamble code */
|
||||
gen_preamble();
|
||||
@@ -56,30 +59,26 @@ phase2()
|
||||
/* Assign bits for event flags */
|
||||
assign_ef_bits();
|
||||
|
||||
/* Generate DB blocks */
|
||||
gen_db_blocks();
|
||||
/* Assign delay id's */
|
||||
assign_delay_ids();
|
||||
|
||||
/* Generate code for each state set */
|
||||
gen_ss_code();
|
||||
|
||||
/* Generate State Blocks */
|
||||
gen_state_blocks();
|
||||
|
||||
/* Generate State Set control blocks as an array */
|
||||
gen_sscb_array();
|
||||
|
||||
/* Generate state program table */
|
||||
gen_state_prog_table();
|
||||
/* Generate tables */
|
||||
gen_tables();
|
||||
|
||||
/* Output global C code */
|
||||
printf("%s\n", global_c_code);
|
||||
gen_global_c_code();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Generate preamble (includes, defines, etc.) */
|
||||
/* Generate preamble (includes, defines, etc.) */
|
||||
gen_preamble()
|
||||
{
|
||||
extern char *prog_name;
|
||||
|
||||
/* Program name (comment) */
|
||||
printf("/* Program \"%s\" */\n", prog_name);
|
||||
|
||||
/* Include files */
|
||||
@@ -87,30 +86,124 @@ gen_preamble()
|
||||
|
||||
/* Local definitions */
|
||||
printf("\n#define NUM_SS %d\n", num_ss);
|
||||
printf("#define NUM_VARS %d\n", num_vars);
|
||||
printf("#define NUM_CHANNELS %d\n", num_channels);
|
||||
|
||||
/* Forward definition of SPROG structure */
|
||||
/* Forward references of tables: */
|
||||
printf("\nextern SPROG %s;\n", prog_name);
|
||||
printf("extern CHAN db_channels[];\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int printTree = FALSE;
|
||||
/* Reconcile all variables in an expression,
|
||||
and tie each to the appropriate VAR struct */
|
||||
reconcile_variables()
|
||||
{
|
||||
extern Expr *ss_list, *exit_code_list;
|
||||
Expr *ssp, *ep;
|
||||
int connect_variable();
|
||||
|
||||
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "reconcile_variables: ss=%s\n", ssp->value);
|
||||
#endif DEBUG
|
||||
traverseExprTree(ssp, E_VAR, 0, connect_variable, 0);
|
||||
}
|
||||
|
||||
/* Same for exit procedure */
|
||||
for (ep = exit_code_list; ep != 0; ep = ep->next)
|
||||
{
|
||||
traverseExprTree(ep, E_VAR, 0, connect_variable, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Connect a variable in an expression to the the Var structure */
|
||||
int connect_variable(ep)
|
||||
Expr *ep;
|
||||
{
|
||||
Var *vp;
|
||||
extern char *stype[];
|
||||
extern int warn_flag;
|
||||
|
||||
vp = (Var *)find_var(ep->value);
|
||||
if (vp == 0)
|
||||
{ /* variable not declared; enter into variable list */
|
||||
if (warn_flag)
|
||||
fprintf(stderr,
|
||||
"Warning: variable \"%s\" is used but not declared.\n",
|
||||
ep->value);
|
||||
vp = allocVar();
|
||||
lstAdd(&var_list, (NODE *)vp);
|
||||
vp->name = ep->value;
|
||||
vp->type = V_NONE; /* undeclared type */
|
||||
vp->length = 0;
|
||||
vp->value = 0;
|
||||
}
|
||||
ep->left = (Expr *)vp; /* make connection */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "connect_variable: %s\n", ep->value);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reconcile state names */
|
||||
reconcile_states()
|
||||
{
|
||||
extern LIST var_list;
|
||||
extern int num_errors;
|
||||
Expr *ssp, *sp, *sp1, tr;
|
||||
|
||||
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
|
||||
{
|
||||
for (sp = ssp->left; sp != 0; sp = sp->next)
|
||||
{
|
||||
/* Check for duplicate state names in this state set */
|
||||
for (sp1 = sp->next; sp1 != 0; sp1 = sp1->next)
|
||||
{
|
||||
if (strcmp(sp->value, sp1->value) == 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"State \"%s\" is duplicated in state set \"%s\"\n",
|
||||
sp->value, ssp->value);
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find a state by name */
|
||||
Expr *find_state(name, sp)
|
||||
char *name; /* state name */
|
||||
Expr *sp; /* beginning of state list */
|
||||
{
|
||||
while (sp != 0)
|
||||
{
|
||||
if (strcmp(name, sp->value) == 0)
|
||||
return sp;
|
||||
sp = sp->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Generate a C variable declaration for each variable declared in SNL */
|
||||
gen_var_decl()
|
||||
{
|
||||
extern LIST var_list;
|
||||
Var *vp;
|
||||
char *vstr, *vname="User_Var_";
|
||||
int nv;
|
||||
extern LIST var_list;
|
||||
Var *vp;
|
||||
char *vstr;
|
||||
int nv;
|
||||
extern int reent_flag;
|
||||
|
||||
printf("\n/* Variable declarations */\n");
|
||||
for (nv=0, vp = firstVar(&var_list); vp != NULL; nv++, vp = nextVar(vp))
|
||||
{
|
||||
if (vp->type != V_EVFLAG)
|
||||
printf("#define %s %s.var%d\n", vp->name, vname, nv);
|
||||
}
|
||||
printf("static struct %s {\n", vname);
|
||||
|
||||
/* Convert internal type to `C' type */
|
||||
if (reent_flag)
|
||||
printf("static struct UserVar {\n");
|
||||
for (nv=0, vp = firstVar(&var_list); vp != NULL; nv++, vp = nextVar(vp))
|
||||
{
|
||||
switch (vp->type)
|
||||
@@ -119,7 +212,8 @@ gen_var_decl()
|
||||
vstr = "char";
|
||||
break;
|
||||
case V_INT:
|
||||
vstr = "int";
|
||||
case V_LONG:
|
||||
vstr = "long";
|
||||
break;
|
||||
case V_SHORT:
|
||||
vstr = "short";
|
||||
@@ -134,290 +228,74 @@ gen_var_decl()
|
||||
vstr = "char";
|
||||
break;
|
||||
case V_EVFLAG:
|
||||
case V_NONE:
|
||||
vstr = NULL;
|
||||
break;
|
||||
default:
|
||||
vstr = "int";
|
||||
break;
|
||||
}
|
||||
|
||||
if (vstr != NULL)
|
||||
{
|
||||
printf("\t%s\tvar%d", vstr, nv);
|
||||
/* Array? */
|
||||
if (vp->length > 0)
|
||||
printf("[%d];\n", vp->length);
|
||||
else if (vp->type == V_STRING)
|
||||
printf("[MAX_STRING_SIZE];\n");
|
||||
if (reent_flag)
|
||||
printf("\t");
|
||||
else
|
||||
printf(";\n");
|
||||
printf("static ");
|
||||
printf("%s\t%s", vstr, vp->name);
|
||||
if (vp->length > 0)
|
||||
printf("[%d]", vp->length);
|
||||
else if (vp->type == V_STRING)
|
||||
printf("[MAX_STRING_SIZE]");
|
||||
printf(";\n");
|
||||
}
|
||||
}
|
||||
printf("} %s;\n", vname);
|
||||
if (reent_flag)
|
||||
printf("};\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate definition C code (C code in definition section) */
|
||||
gen_defn_c_code()
|
||||
{
|
||||
extern LIST defn_c_list;
|
||||
Action *ap;
|
||||
extern Expr *defn_c_list;
|
||||
Expr *ep;
|
||||
|
||||
ap = firstAction(&defn_c_list);
|
||||
if (ap != NULL)
|
||||
ep = defn_c_list;
|
||||
if (ep != NULL)
|
||||
{
|
||||
printf("\n\t/* C code definitions */\n");
|
||||
for (; ap != NULL; ap = nextAction(ap))
|
||||
for (; ep != NULL; ep = ep->next)
|
||||
{
|
||||
print_line_num(ap->line_num);
|
||||
printf("%s\n", ap->stmt.c_code);
|
||||
print_line_num(ep->line_num, ep->src_file);
|
||||
printf("%s\n", ep->left);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate the structure with data for a state program table (SPROG) */
|
||||
gen_state_prog_table()
|
||||
/* Generate global C code (C code following state program) */
|
||||
gen_global_c_code()
|
||||
{
|
||||
extern char *prog_param;
|
||||
extern Expr *global_c_list;
|
||||
Expr *ep;
|
||||
|
||||
printf("\n/* Program parameter list */\n");
|
||||
|
||||
printf("static char prog_param[] = \"%s\";\n", prog_param);
|
||||
|
||||
printf("\n/* State Program table (global) */\n");
|
||||
|
||||
printf("SPROG %s = {\n", prog_name);
|
||||
|
||||
printf("\t%d,\t/* magic number */\n", MAGIC);
|
||||
|
||||
printf("\t0,\t/* task id */\n");
|
||||
|
||||
printf("\t0,\t/* task_is_deleted */\n");
|
||||
|
||||
printf("\t1,\t/* relative task priority */\n");
|
||||
|
||||
printf("\t0,\t/* sem_id */\n");
|
||||
|
||||
printf("\tdb_channels,\t/* *channels */\n");
|
||||
|
||||
printf("\tNUM_CHANNELS,\t/* nchan */\n");
|
||||
|
||||
printf("\tsscb,\t/* *sscb */\n");
|
||||
|
||||
printf("\tNUM_SS,\t/* nss */\n");
|
||||
|
||||
printf("\t&User_Var_,\t/* ptr to user area */\n");
|
||||
|
||||
printf("\t4,\t/* user area size */\n");
|
||||
|
||||
printf("\t\"%s\",\t/* *name */\n", prog_name);
|
||||
|
||||
printf("\tprog_param\t/* *params */\n");
|
||||
|
||||
printf("};\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate database blocks with structure and data for each defined channel */
|
||||
gen_db_blocks()
|
||||
{
|
||||
extern LIST chan_list;
|
||||
Chan *cp;
|
||||
int nchan;
|
||||
|
||||
printf("\n/* Database Blocks */\n");
|
||||
printf("static CHAN db_channels[NUM_CHANNELS] = {\n");
|
||||
nchan = 0;
|
||||
for (cp = firstChan(&chan_list); cp != NULL; cp = nextChan(cp))
|
||||
ep = global_c_list;
|
||||
if (ep != NULL)
|
||||
{
|
||||
/* Only process db variables */
|
||||
if (cp->db_name != NULL)
|
||||
printf("\f\t/* Global C code */\n");
|
||||
for (; ep != NULL; ep = ep->next)
|
||||
{
|
||||
if (nchan > 0)
|
||||
printf(",\n");
|
||||
fill_db_block(cp);
|
||||
nchan++;
|
||||
print_line_num(ep->line_num, ep->src_file);
|
||||
printf("%s\n", ep->left);
|
||||
}
|
||||
}
|
||||
printf("\n};\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill in a db block with data (all elements for "CHAN" struct) */
|
||||
fill_db_block(cp)
|
||||
Chan *cp;
|
||||
{
|
||||
Var *vp;
|
||||
char *dbr_type_string;
|
||||
extern char *prog_name;
|
||||
int size, ev_flag;
|
||||
|
||||
vp = cp->var;
|
||||
switch (vp->type)
|
||||
{
|
||||
case V_SHORT:
|
||||
dbr_type_string = "DBR_INT";
|
||||
size = sizeof(short);
|
||||
break;
|
||||
case V_INT:
|
||||
dbr_type_string = "DBR_INT";
|
||||
size = sizeof(int);
|
||||
break;
|
||||
case V_CHAR:
|
||||
dbr_type_string = "DBR_INT";
|
||||
size = sizeof(char);
|
||||
break;
|
||||
case V_FLOAT:
|
||||
dbr_type_string = "DBR_FLOAT";
|
||||
size = sizeof(float);
|
||||
break;
|
||||
case V_DOUBLE:
|
||||
dbr_type_string = "DBR_FLOAT";
|
||||
size = sizeof(double);
|
||||
break;
|
||||
case V_STRING:
|
||||
dbr_type_string = "DBR_STRING";
|
||||
size = sizeof(char);
|
||||
break;
|
||||
}
|
||||
/* fill in the CHAN structure */
|
||||
printf("\t\"%s\"", cp->db_name);/* unexpanded db channel name */
|
||||
|
||||
printf(", (char *) 0"); /* ch'l name after macro expansion */
|
||||
|
||||
printf(", (chid)0"); /* reserve place for chid */
|
||||
|
||||
if (vp->type == V_STRING)
|
||||
printf(", %s", vp->name); /* variable ptr */
|
||||
else
|
||||
printf(", &%s", vp->name); /* variable ptr */
|
||||
if (vp->length != 0)
|
||||
printf("[%d]", cp->offset); /* array offset */
|
||||
|
||||
printf(", %d", size); /* element size (bytes) */
|
||||
|
||||
printf(",\n\t %s", dbr_type_string);/* DB request conversion type */
|
||||
|
||||
printf(", %d", vp->length); /* array length (of the variable) */
|
||||
|
||||
printf(", %d", cp->mon_flag); /* monitor flag */
|
||||
|
||||
printf(", %d", cp->length); /* count for db requests */
|
||||
|
||||
printf(", %g", cp->delta); /* monitor delta */
|
||||
|
||||
printf(", %g", cp->timeout); /* monitor timeout */
|
||||
|
||||
printf(", &%s", prog_name); /* ptr to state program structure */
|
||||
|
||||
vp = cp->ef_var;
|
||||
if (vp == 0)
|
||||
ev_flag = 0;
|
||||
else
|
||||
ev_flag = 1 << vp->ef_num;
|
||||
printf(", %d", ev_flag); /* sync event flag */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate structure and data for state blocks (STATE) */
|
||||
gen_state_blocks()
|
||||
{
|
||||
extern LIST ss_list;
|
||||
StateSet *ssp;
|
||||
State *sp;
|
||||
int nstates;
|
||||
|
||||
printf("\n/* State Blocks */\n");
|
||||
printf("/* action_func, event_func, delay_func, event_flag_mask");
|
||||
printf(", *delay, *name */\n");
|
||||
|
||||
for (ssp = firstSS(&ss_list); ssp != NULL; ssp = nextSS(ssp))
|
||||
{
|
||||
printf("\nstatic STATE state_%s[] = {\n", ssp->ss_name);
|
||||
nstates = 0;
|
||||
for (sp = firstState(&ssp->S_list); sp != NULL; sp = nextState(sp))
|
||||
{
|
||||
if (nstates > 0)
|
||||
printf(",\n\n");
|
||||
nstates++;
|
||||
fill_state_block(sp, ssp->ss_name);
|
||||
}
|
||||
printf("\n};\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill in data for a the state block */
|
||||
fill_state_block(sp, ss_name)
|
||||
State *sp;
|
||||
char *ss_name;
|
||||
{
|
||||
printf("\t/* State \"%s\"*/\n", sp->state_name);
|
||||
|
||||
printf("\ta_%s_%s,\t/* action_function */\n", ss_name, sp->state_name);
|
||||
|
||||
printf("\te_%s_%s,\t/* event_function */\n", ss_name, sp->state_name);
|
||||
|
||||
printf("\td_%s_%s,\t/* delay_function */\n", ss_name, sp->state_name);
|
||||
|
||||
printf("\t%d,\t/* event_flag_mask */\n", sp->event_flag_mask);
|
||||
|
||||
printf("\t\"%s\"\t/* *name */", sp->state_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate a state set control block (SSCB) for each state set */
|
||||
gen_sscb_array()
|
||||
{
|
||||
extern LIST ss_list;
|
||||
StateSet *ssp;
|
||||
int nss, nstates, n;
|
||||
|
||||
printf("\n/* State Set Control Blocks */\n");
|
||||
printf("static SSCB sscb[NUM_SS] = {\n");
|
||||
nss = 0;
|
||||
for (ssp = firstSS(&ss_list); ssp != NULL; ssp = nextSS(ssp))
|
||||
{
|
||||
if (nss > 0)
|
||||
printf(",\n\n");
|
||||
nss++;
|
||||
nstates = lstCount((NODE *)&ssp->S_list);
|
||||
|
||||
printf("\t/* State set \"%s\"*/\n", ssp->ss_name);
|
||||
|
||||
printf("\t0, 1, 0,\t/* task_id, task_prioity, sem_id */\n");
|
||||
|
||||
printf("\t0, 0,\t\t/* event_flag, event_flag_mask */\n");
|
||||
|
||||
printf("\t%d, state_%s,\t/* num_states, *states */\n", nstates,
|
||||
ssp->ss_name);
|
||||
|
||||
printf("\tNULL, NULL,\t/* *current_state, *next_state */\n");
|
||||
|
||||
printf("\t0, FALSE,\t/* trans_number, action_complete */\n");
|
||||
|
||||
printf("\t%d,\t/* number of time-out structures */\n", ssp->ndelay);
|
||||
|
||||
printf("\t/* array of time-out values: */\n\t");
|
||||
for (n = 0; n < MAX_NDELAY; n++)
|
||||
printf("0,");
|
||||
printf("\n");
|
||||
|
||||
printf("\t0,\t/* time (ticks) when state was entered */\n");
|
||||
|
||||
printf("\t\"%s\"\t\t/* ss_name */", ssp->ss_name);
|
||||
}
|
||||
printf("\n};\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns number of db channels defined & inserts index into each channel struct */
|
||||
db_chan_count()
|
||||
{
|
||||
extern LIST var_list;
|
||||
extern LIST chan_list;
|
||||
int nchan;
|
||||
Chan *cp;
|
||||
|
||||
@@ -428,48 +306,156 @@ db_chan_count()
|
||||
{
|
||||
cp->index = nchan;
|
||||
nchan++;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "db_name=%s, index=%d\n",
|
||||
cp->db_name, cp->index);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return nchan;
|
||||
}
|
||||
|
||||
|
||||
/* Given a state name and state set struct, find the corresponding
|
||||
state struct and return its index (1-st one is 0) */
|
||||
state_block_index_from_name(ssp, state_name)
|
||||
StateSet *ssp;
|
||||
char *state_name;
|
||||
{
|
||||
State *sp;
|
||||
int index;
|
||||
|
||||
index = 0;
|
||||
for (sp = firstState(&ssp->S_list); sp != NULL; sp = nextState(sp))
|
||||
{
|
||||
if (strcmp(state_name, sp->state_name) == 0)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return -1; /* State name non-existant */
|
||||
}
|
||||
|
||||
/* Assign bits to event flags */
|
||||
/* Assign bits to event flags and database variables */
|
||||
assign_ef_bits()
|
||||
{
|
||||
extern LIST var_list;
|
||||
Var *vp;
|
||||
int ef_num;
|
||||
extern LIST var_list;
|
||||
Var *vp;
|
||||
Chan *cp;
|
||||
int ef_num;
|
||||
extern int num_channels;
|
||||
|
||||
ef_num = 0;
|
||||
ef_num = num_channels + 1; /* start with 1-st avail mask bit */
|
||||
printf("\n/* Event flags */\n");
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\nAssign values to event flags\n");
|
||||
#endif
|
||||
for (vp = firstVar(&var_list); vp != NULL; vp = nextVar(vp))
|
||||
{
|
||||
cp = vp->chan;
|
||||
/* First see if this is an event flag */
|
||||
if (vp->type == V_EVFLAG)
|
||||
{
|
||||
vp->ef_num = ef_num;
|
||||
printf("#define %s (1<<%d)\n", vp->name, ef_num);
|
||||
ef_num++;
|
||||
if (cp != 0)
|
||||
vp->ef_num = cp->index + 1; /* sync'ed */
|
||||
else
|
||||
vp->ef_num = ef_num++;
|
||||
printf("#define %s\t%d\n", vp->name, vp->ef_num);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (cp != 0)
|
||||
vp->ef_num = cp->index + 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s: ef_num=%d\n", vp->name, vp->ef_num);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Assign a delay id to each "delay()" in an event (when()) expression */
|
||||
assign_delay_ids()
|
||||
{
|
||||
extern Expr *ss_list;
|
||||
Expr *ssp, *sp, *tp;
|
||||
int delay_id;
|
||||
int assign_next_delay_id();
|
||||
|
||||
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
|
||||
{
|
||||
for (sp = ssp->left; sp != 0; sp = sp->next)
|
||||
{
|
||||
/* Each state has it's own delay id's */
|
||||
delay_id = 0;
|
||||
for (tp = sp->left; tp != 0; tp = tp->next)
|
||||
{ /* traverse event expression only */
|
||||
traverseExprTree(tp->left, E_FUNC, "delay",
|
||||
assign_next_delay_id, &delay_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assign_next_delay_id(ep, delay_id)
|
||||
Expr *ep;
|
||||
int *delay_id;
|
||||
{
|
||||
ep->right = (Expr *)*delay_id;
|
||||
*delay_id += 1;
|
||||
}
|
||||
|
||||
/* Traverse the expression tree, and call the supplied
|
||||
* function on matched conditions */
|
||||
traverseExprTree(ep, type, value, funcp, argp)
|
||||
Expr *ep; /* ptr to start of expression */
|
||||
int type; /* to search for */
|
||||
char *value; /* with optional matching value */
|
||||
void (*funcp)(); /* function to call */
|
||||
void *argp; /* ptr to argument to pass on to function */
|
||||
{
|
||||
Expr *ep1;
|
||||
extern char *stype[];
|
||||
|
||||
if (ep == 0)
|
||||
return;
|
||||
|
||||
if (printTree)
|
||||
fprintf(stderr, "traverseExprTree: type=%s, value=%s\n",
|
||||
stype[ep->type], ep->value);
|
||||
|
||||
/* Call the function? */
|
||||
if ((ep->type == type) &&
|
||||
(value == 0 || strcmp(ep->value, value) == 0) )
|
||||
{
|
||||
funcp(ep, argp);
|
||||
}
|
||||
|
||||
/* Continue traversing the expression tree */
|
||||
switch(ep->type)
|
||||
{
|
||||
case E_EMPTY:
|
||||
case E_VAR:
|
||||
case E_CONST:
|
||||
case E_STRING:
|
||||
case E_TEXT:
|
||||
break;
|
||||
|
||||
case E_PAREN:
|
||||
case E_UNOP:
|
||||
case E_SS:
|
||||
case E_STATE:
|
||||
case E_FUNC:
|
||||
case E_CMPND:
|
||||
case E_STMT:
|
||||
case E_ELSE:
|
||||
for (ep1 = ep->left; ep1 != 0; ep1 = ep1->next)
|
||||
{
|
||||
traverseExprTree(ep1, type, value, funcp, argp);
|
||||
}
|
||||
break;
|
||||
|
||||
case E_WHEN:
|
||||
case E_ASGNOP:
|
||||
case E_BINOP:
|
||||
case E_SUBSCR:
|
||||
case E_IF:
|
||||
case E_WHILE:
|
||||
for (ep1 = ep->left; ep1 != 0; ep1 = ep1->next)
|
||||
{
|
||||
traverseExprTree(ep1, type, value, funcp, argp);
|
||||
}
|
||||
for (ep1 = ep->right; ep1 != 0; ep1 = ep1->next)
|
||||
{
|
||||
traverseExprTree(ep1, type, value, funcp, argp);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
fprintf(stderr, "traverseExprTree: type=%d???\n", ep->type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_ca.c 1.7 2/4/91
|
||||
@(#)seq_ca.c 1.10 4/24/91
|
||||
DESCRIPTION: Seq_ca.c: Channel access interface for sequencer
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
@@ -13,140 +13,354 @@
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#define MACRO_STR_LEN (MAX_STRING_SIZE+1)
|
||||
|
||||
/* Connect to the database channels through channel access */
|
||||
connect_db_channels(sp_ptr, macro_tbl)
|
||||
SPROG *sp_ptr;
|
||||
struct macro *macro_tbl;
|
||||
connect_db_channels(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
CHAN *db_ptr;
|
||||
int status, i;
|
||||
CHAN *db_ptr;
|
||||
int status, i;
|
||||
MACRO *macro_tbl;
|
||||
extern seq_conn_handler();
|
||||
|
||||
/* Initialize CA task */
|
||||
ca_task_initialize();
|
||||
|
||||
sp_ptr->conn_count = 0;
|
||||
macro_tbl = sp_ptr->mac_ptr;
|
||||
|
||||
/* Search for all channels */
|
||||
db_ptr = sp_ptr->channels;
|
||||
for (i = 0; i < sp_ptr->nchan; i++)
|
||||
{
|
||||
/* Do macro substitution */
|
||||
db_ptr->db_name = seqAlloc(MACRO_STR_LEN);
|
||||
macEval(db_ptr->db_uname, db_ptr->db_name, MACRO_STR_LEN,
|
||||
/* Do macro substitution on channel name */
|
||||
db_ptr->db_name = seqAlloc(sp_ptr, MACRO_STR_LEN);
|
||||
seqMacEval(db_ptr->db_uname, db_ptr->db_name, MACRO_STR_LEN,
|
||||
macro_tbl);
|
||||
printf(" %d: %s\n", i, db_ptr->db_name);
|
||||
status = ca_search(db_ptr->db_name, &(db_ptr->chid));
|
||||
#ifdef DEBUG
|
||||
printf("connect to \"%s\"\n", db_ptr->db_name);
|
||||
#endif DEBUG
|
||||
/* Connect to it */
|
||||
status = ca_build_and_connect(
|
||||
db_ptr->db_name, /* DB channel name */
|
||||
TYPENOTCONN, /* Don't get initial value */
|
||||
0, /* get count (n/a) */
|
||||
&(db_ptr->chid), /* ptr to chid */
|
||||
0, /* ptr to value (n/a) */
|
||||
seq_conn_handler, /* connection handler routine */
|
||||
db_ptr); /* user ptr is CHAN structure */
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_search");
|
||||
ca_task_exit();
|
||||
return -1;
|
||||
}
|
||||
db_ptr++;
|
||||
}
|
||||
/* Clear monitor indicator */
|
||||
db_ptr->monitored = FALSE;
|
||||
|
||||
/* Wait for returns from "ca_search" */
|
||||
status = ca_pend_io(10.0);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_pend_io");
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
db_ptr = sp_ptr->channels;
|
||||
for (i = 0; i < sp_ptr->nchan; i++)
|
||||
{
|
||||
printf("\"%s\" ca_search() returned: chid=0x%x\n",
|
||||
db_ptr->db_name, db_ptr->chid);
|
||||
db_ptr++;
|
||||
}
|
||||
#endif
|
||||
printf("All db channels connected\n");
|
||||
return 0;
|
||||
}
|
||||
/* Issue monitor requests */
|
||||
issue_monitor_requests(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
CHAN *db_ptr;
|
||||
int status, i;
|
||||
int seq_event_handler();
|
||||
|
||||
db_ptr = sp_ptr->channels;
|
||||
for (i = 0; i < sp_ptr->nchan; i++)
|
||||
{
|
||||
/* Issue monitor requests */
|
||||
if (db_ptr->mon_flag)
|
||||
{
|
||||
status = ca_add_general_event(
|
||||
db_ptr->dbr_type, /* requested type */
|
||||
db_ptr->chid, /* chid */
|
||||
seq_event_handler, /* function to call */
|
||||
db_ptr, /* user arg is db entry */
|
||||
db_ptr->delta, /* pos. delta value */
|
||||
db_ptr->delta, /* neg. delta value */
|
||||
db_ptr->timeout, /* timeout */
|
||||
0 /* no event id */);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_search");
|
||||
ca_task_exit();
|
||||
return -1;
|
||||
}
|
||||
seq_pvMonitor(sp_ptr, 0, db_ptr);
|
||||
}
|
||||
db_ptr++;
|
||||
}
|
||||
ca_flush_io();
|
||||
|
||||
if (sp_ptr->conn_flag)
|
||||
{ /* Wait for all connections to complete */
|
||||
while (sp_ptr->conn_count < sp_ptr->nchan)
|
||||
taskDelay(30);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Channel access events (monitors) come here */
|
||||
seq_event_handler(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
CHAN *db_ptr;
|
||||
int i, nbytes, count;
|
||||
int nss;
|
||||
SPROG *sp_ptr;
|
||||
CHAN *db_ptr;
|
||||
struct dbr_sts_char *dbr_sts_ptr;
|
||||
int i, nbytes;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
db_ptr = (CHAN *)args.usr;
|
||||
|
||||
/* Get ptr to data & status structure */
|
||||
dbr_sts_ptr = (struct dbr_sts_char *)args.dbr;
|
||||
|
||||
/* Copy value returned into user variable */
|
||||
count = db_ptr->count;
|
||||
if (count == 0)
|
||||
count = 1;
|
||||
nbytes = db_ptr->size * count;
|
||||
bcopy(args.dbr, db_ptr->var, nbytes);
|
||||
#ifdef DEBUG
|
||||
printf("seq_event_handler: ");
|
||||
if (db_ptr->dbr_type == DBR_FLOAT)
|
||||
printf("%s=%g\n", db_ptr->db_name, *(float *)db_ptr->var);
|
||||
else if (db_ptr->dbr_type == DBR_INT)
|
||||
{
|
||||
i = *(short *)args.dbr;
|
||||
printf("%s=%d\n", db_ptr->db_name, i);
|
||||
}
|
||||
else
|
||||
printf("?\n");
|
||||
#endif DEBUG
|
||||
nbytes = db_ptr->size * db_ptr->count;
|
||||
bcopy(&(dbr_sts_ptr->value), db_ptr->var, nbytes);
|
||||
|
||||
/* Copy status & severity */
|
||||
db_ptr->status = dbr_sts_ptr->status;
|
||||
db_ptr->severity = dbr_sts_ptr->severity;
|
||||
|
||||
/* Process event handling in each state set */
|
||||
sp_ptr = db_ptr->sprog; /* State program that owns this db entry */
|
||||
|
||||
/* Set synchronization event flag (if it exists) for each state set */
|
||||
if (db_ptr->ev_flag != 0)
|
||||
seq_efSet(sp_ptr, 0, db_ptr->ev_flag);
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
seq_efSet(sp_ptr, 0, db_ptr->index + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Sequencer connection handler:
|
||||
Called each time a connection is established or broken */
|
||||
seq_conn_handler(args)
|
||||
struct connection_handler_args args;
|
||||
{
|
||||
CHAN *db_ptr;
|
||||
SPROG *sp_ptr;
|
||||
|
||||
|
||||
/* user argument (from ca_search() */
|
||||
db_ptr = (CHAN *)ca_puser(args.chid);
|
||||
|
||||
/* State program that owns this db entry */
|
||||
sp_ptr = db_ptr->sprog;
|
||||
|
||||
/* Check for connected */
|
||||
if (ca_field_type(args.chid) == TYPENOTCONN)
|
||||
{
|
||||
if (ss_ptr->action_complete)
|
||||
db_ptr->connected = FALSE;
|
||||
sp_ptr->conn_count--;
|
||||
seqLog(sp_ptr, "Channel \"%s\" disconnected\n", db_ptr->db_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
db_ptr->connected = TRUE;
|
||||
sp_ptr->conn_count++;
|
||||
seqLog(sp_ptr, "Channel \"%s\" connected\n", db_ptr->db_name);
|
||||
if (db_ptr->count > ca_element_count(args.chid))
|
||||
{
|
||||
semGive(ss_ptr->sem_id);
|
||||
db_ptr->count = ca_element_count(args.chid);
|
||||
seqLog(sp_ptr, "\"%s\": reset count to %d\n",
|
||||
db_ptr->db_name, db_ptr->count);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
seq_efSet(sp_ptr, 0, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
seq_efSet(sp_ptr, dummy, ev_flag)
|
||||
SPROG *sp_ptr;
|
||||
void *dummy;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
int nss;
|
||||
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
/* For all state sets: */
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
/* Apply resource lock */
|
||||
semTake(sp_ptr->sem_id, 0);
|
||||
|
||||
/* Test for possible event trig based on bit mask for this state */
|
||||
if ( (ev_flag == 0) || bitTest(ss_ptr->pMask, ev_flag) )
|
||||
{
|
||||
bitSet(ss_ptr->events, ev_flag);
|
||||
semGive(ss_ptr->sem_id); /* wake up the ss task */
|
||||
}
|
||||
|
||||
/* Unlock resource */
|
||||
semGive(sp_ptr->sem_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Test event flag against outstanding events */
|
||||
seq_efTest(sp_ptr, ss_ptr, ev_flag)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
return bitTest(ss_ptr->events, ev_flag);
|
||||
}
|
||||
/* Get DB value (uses channel access) */
|
||||
seq_pvGet(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
extern seq_callback_handler();
|
||||
extern int async_flag;
|
||||
|
||||
/* Check for channel connected */
|
||||
if (!db_ptr->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
db_ptr->get_complete = 0;
|
||||
/* Asynchronous get? */
|
||||
if (sp_ptr->async_flag)
|
||||
{
|
||||
status = ca_array_get_callback(
|
||||
db_ptr->get_type, /* db request type */
|
||||
db_ptr->count, /* element count */
|
||||
db_ptr->chid, /* chid */
|
||||
seq_callback_handler, /* callback handler */
|
||||
db_ptr); /* user arg */
|
||||
|
||||
/* Note: CA buffer is not flushed */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Synchronous get (wait for completion) */
|
||||
status = ca_array_get(
|
||||
db_ptr->put_type, /* db request type */
|
||||
db_ptr->count, /* element count */
|
||||
db_ptr->chid, /* chid */
|
||||
db_ptr->var); /* value */
|
||||
|
||||
if (status == ECA_BADTYPE)
|
||||
{
|
||||
seqLog(sp_ptr, "Bad type: pvGet() on %s\n", db_ptr->db_name);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (status == ECA_BADCHID)
|
||||
{
|
||||
seqLog(sp_ptr, "Disconencted: pvGet() on %s\n", db_ptr->db_name);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Wait for completion */
|
||||
status = ca_pend_io(10.0);
|
||||
db_ptr->get_complete = TRUE;
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
seqLog(sp_ptr, "time-out: pvGet() on %s\n", db_ptr->db_name);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Sequencer callback handler - called when a "get" completes */
|
||||
seq_callback_handler(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
SPROG *sp_ptr;
|
||||
CHAN *db_ptr;
|
||||
struct dbr_sts_char *dbr_sts_ptr;
|
||||
int i, nbytes;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
db_ptr = (CHAN *)args.usr;
|
||||
|
||||
/* Get ptr to data & status structure */
|
||||
dbr_sts_ptr = (struct dbr_sts_char *)args.dbr;
|
||||
|
||||
/* Copy value returned into user variable */
|
||||
nbytes = db_ptr->size * db_ptr->count;
|
||||
bcopy(&(dbr_sts_ptr->value), db_ptr->var, nbytes);
|
||||
|
||||
/* Copy status & severity */
|
||||
db_ptr->status = dbr_sts_ptr->status;
|
||||
db_ptr->severity = dbr_sts_ptr->severity;
|
||||
|
||||
/* Set get complete flag */
|
||||
db_ptr->get_complete = TRUE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Flush requests */
|
||||
seq_pvFlush()
|
||||
{
|
||||
ca_flush_io();
|
||||
}
|
||||
|
||||
/* Put DB value (uses channel access) */
|
||||
seq_pvPut(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!db_ptr->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
status = ca_array_put(db_ptr->put_type, db_ptr->count,
|
||||
db_ptr->chid, db_ptr->var);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
seqLog(sp_ptr, "pvPut on \"%s\" failed (%d)\n",
|
||||
db_ptr->db_name, status);
|
||||
seqLog(sp_ptr, " put_type=%d\n", db_ptr->put_type);
|
||||
seqLog(sp_ptr, " size=%d, count=%d\n", db_ptr->size, db_ptr->count);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/* Initiate a monitor on a channel */
|
||||
seq_pvMonitor(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
extern seq_event_handler();
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("monitor \"%s\"\n", db_ptr->db_name);
|
||||
#endif DEBUG
|
||||
|
||||
if (db_ptr->monitored)
|
||||
return -1;
|
||||
|
||||
status = ca_add_array_event(
|
||||
db_ptr->get_type, /* requested type */
|
||||
db_ptr->count, /* element count */
|
||||
db_ptr->chid, /* chid */
|
||||
seq_event_handler, /* function to call */
|
||||
db_ptr, /* user arg (db struct) */
|
||||
db_ptr->delta, /* pos. delta value */
|
||||
db_ptr->delta, /* neg. delta value */
|
||||
db_ptr->timeout, /* timeout */
|
||||
&db_ptr->evid); /* where to put event id */
|
||||
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_add_array_event");
|
||||
ca_task_exit(); /* this is serious */
|
||||
return -1;
|
||||
}
|
||||
ca_flush_io();
|
||||
|
||||
db_ptr->monitored = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cancel a monitor */
|
||||
seq_pvStopMonitor(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!db_ptr->monitored)
|
||||
return -1;
|
||||
|
||||
status = ca_clear_event(db_ptr->evid);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_clear_event");
|
||||
return status;
|
||||
}
|
||||
|
||||
db_ptr->monitored = FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_mac.c 1.1 11/9/90
|
||||
@(#)seq_mac.c 1.3 4/23/91
|
||||
DESCRIPTION: Macro routines for Sequencer.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
@@ -13,17 +13,10 @@
|
||||
#include "vxWorks.h"
|
||||
#include "seq.h"
|
||||
|
||||
LOCAL int macNameLth();
|
||||
LOCAL int macParseName();
|
||||
LOCAL int macParseValue();
|
||||
LOCAL char *skipBlanks();
|
||||
/*#define DEBUG*/
|
||||
|
||||
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
/* macTblInit - initialize macro table */
|
||||
macTblInit(mac_ptr)
|
||||
/* seqMacTblInit - initialize macro table */
|
||||
seqMacTblInit(mac_ptr)
|
||||
MACRO *mac_ptr;
|
||||
{
|
||||
int i;
|
||||
@@ -35,17 +28,17 @@ MACRO *mac_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/* macEval - substitute macro value into a string */
|
||||
macEval(pInStr, pOutStr, maxChar, macTbl)
|
||||
/* seqMacEval - substitute macro value into a string */
|
||||
seqMacEval(pInStr, pOutStr, maxChar, macTbl)
|
||||
char *pInStr;
|
||||
char *pOutStr;
|
||||
MACRO *macTbl;
|
||||
{
|
||||
char *pMacVal, *pTmp;
|
||||
int nameLth, valLth;
|
||||
char *pMacVal, *pTmp;
|
||||
int nameLth, valLth;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("macEval: InStr=%s\n", pInStr);
|
||||
printf("seqMacEval: InStr=%s\n", pInStr);
|
||||
#endif
|
||||
pTmp = pOutStr;
|
||||
while (*pInStr != 0 && maxChar > 0)
|
||||
@@ -58,7 +51,7 @@ MACRO *macTbl;
|
||||
printf("Name=%s[%d]\n", pInStr, nameLth);
|
||||
#endif
|
||||
/* Find macro value from macro name */
|
||||
pMacVal = macValGet(pInStr, nameLth, macTbl);
|
||||
pMacVal = seqMacValGet(pInStr, nameLth, macTbl);
|
||||
if (pMacVal != NULL)
|
||||
{ /* Substitute macro value */
|
||||
valLth = strlen(pMacVal);
|
||||
@@ -89,8 +82,8 @@ MACRO *macTbl;
|
||||
*pOutStr == 0;
|
||||
}
|
||||
|
||||
/* macValGet - given macro name, return pointer to its value */
|
||||
char *macValGet(macName, macNameLth, macTbl)
|
||||
/* seqMacValGet - given macro name, return pointer to its value */
|
||||
char *seqMacValGet(macName, macNameLth, macTbl)
|
||||
char *macName;
|
||||
int macNameLth;
|
||||
MACRO *macTbl;
|
||||
@@ -125,20 +118,22 @@ char *pstr;
|
||||
}
|
||||
return nchar;
|
||||
}
|
||||
/* macParse - parse the macro definition string and build
|
||||
/* seqMacParse - parse the macro definition string and build
|
||||
the macro table (name/value pairs). Returns number of macros parsed.
|
||||
Assumes the table may already contain entries (values may be changed).
|
||||
String for name and value are allocated dynamically from pool.
|
||||
*/
|
||||
int macParse(pMacStr, macTbl)
|
||||
char *pMacStr; /* macro definition string */
|
||||
MACRO *macTbl; /* macro table */
|
||||
int seqMacParse(pMacStr, sp_ptr)
|
||||
char *pMacStr; /* macro definition string */
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
int nMac, nChar;
|
||||
char *skipBlanks();
|
||||
MACRO *pMacTbl;
|
||||
MACRO *macTbl; /* macro table */
|
||||
MACRO *pMacTbl; /* macro tbl entry */
|
||||
char *name, *value;
|
||||
|
||||
macTbl = sp_ptr->mac_ptr;
|
||||
for ( ;; )
|
||||
{
|
||||
/* Skip blanks */
|
||||
@@ -146,10 +141,10 @@ MACRO *macTbl; /* macro table */
|
||||
|
||||
/* Parse the macro name */
|
||||
|
||||
nChar = macParseName(pMacStr);
|
||||
nChar = seqMacParseName(pMacStr);
|
||||
if (nChar == 0)
|
||||
break; /* finished or error */
|
||||
name = seqAlloc(nChar+1);
|
||||
name = seqAlloc(sp_ptr, nChar+1);
|
||||
if (name == NULL)
|
||||
break;
|
||||
bcopy(pMacStr, name, nChar);
|
||||
@@ -160,7 +155,7 @@ MACRO *macTbl; /* macro table */
|
||||
pMacStr += nChar;
|
||||
|
||||
/* Find a slot in the table */
|
||||
pMacTbl = macTblGet(name, macTbl);
|
||||
pMacTbl = seqMacTblGet(name, macTbl);
|
||||
if (pMacTbl == NULL)
|
||||
break; /* table is full */
|
||||
if (pMacTbl->name == NULL)
|
||||
@@ -180,10 +175,10 @@ MACRO *macTbl; /* macro table */
|
||||
pMacStr = skipBlanks(pMacStr);
|
||||
|
||||
/* Parse the value */
|
||||
nChar = macParseValue(pMacStr);
|
||||
nChar = seqMacParseValue(pMacStr);
|
||||
if (nChar == 0)
|
||||
break;
|
||||
value = seqAlloc(nChar+1);
|
||||
value = seqAlloc(sp_ptr, nChar+1);
|
||||
if (value == NULL)
|
||||
break;
|
||||
bcopy(pMacStr, value, nChar);
|
||||
@@ -208,7 +203,7 @@ MACRO *macTbl; /* macro table */
|
||||
}
|
||||
|
||||
|
||||
LOCAL int macParseName(pStr)
|
||||
LOCAL int seqMacParseName(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
int nChar;
|
||||
@@ -228,7 +223,7 @@ char *pStr;
|
||||
return nChar;
|
||||
}
|
||||
|
||||
LOCAL int macParseValue(pStr)
|
||||
LOCAL int seqMacParseValue(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
int nChar;
|
||||
@@ -251,9 +246,9 @@ char *pChar;
|
||||
return pChar;
|
||||
}
|
||||
|
||||
/* macTblGet - find a match for the specified name, otherwise
|
||||
/* seqMacTblGet - find a match for the specified name, otherwise
|
||||
return an empty slot in macro table */
|
||||
LOCAL MACRO *macTblGet(name, macTbl)
|
||||
LOCAL MACRO *seqMacTblGet(name, macTbl)
|
||||
char *name; /* macro name */
|
||||
MACRO *macTbl;
|
||||
{
|
||||
@@ -261,7 +256,7 @@ MACRO *macTbl;
|
||||
MACRO *pMacTbl;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("macTblGet: name=%s\n", name);
|
||||
printf("seqMacTblGet: name=%s\n", name);
|
||||
#endif
|
||||
for (i = 0, pMacTbl = macTbl; i < MAX_MACROS; i++, pMacTbl++)
|
||||
{
|
||||
|
||||
@@ -3,15 +3,18 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq.c 1.8 2/1/91
|
||||
@(#)seq_main.c 1.2 4/23/91
|
||||
DESCRIPTION: Seq() initiates a sequence as a group of cooperating
|
||||
tasks. An optional string parameter specifies the values for
|
||||
macros.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
|
||||
HISTORY:
|
||||
23apr91,ajk Fixed problem with state program invoking the sequencer.
|
||||
***************************************************************************/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#include "seq.h"
|
||||
#include "vxWorks.h"
|
||||
@@ -19,6 +22,8 @@
|
||||
|
||||
#define SCRATCH_SIZE (MAX_MACROS*(MAX_STRING_SIZE+1)*12)
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
/* The following variable points to the area allocated for the
|
||||
parent state program and its corresponding state sets.
|
||||
It is declared a "task variable" and is shared by only these
|
||||
@@ -26,94 +31,52 @@
|
||||
It is also used as a flag to indicate that the "taskDeleteHookAdd()"
|
||||
routine has been called (we only want to do that once after VxWorks boots).
|
||||
*/
|
||||
|
||||
|
||||
LOCAL TASK *alloc_task_area();
|
||||
LOCAL count_states();
|
||||
LOCAL copy_sprog();
|
||||
LOCAL init_sprog();
|
||||
LOCAL init_sscb();
|
||||
|
||||
|
||||
|
||||
TASK *task_area_ptr = NULL;
|
||||
SPROG *seq_task_ptr = NULL;
|
||||
|
||||
/* User entry routine to initiate a state program */
|
||||
seq(sp_ptr, macro_def, stack_size)
|
||||
SPROG *sp_ptr; /* ptr to state program table */
|
||||
char *macro_def; /* macro def'n string */
|
||||
int stack_size; /* stack size */
|
||||
seq(sp_ptr_orig, macro_def, stack_size)
|
||||
SPROG *sp_ptr_orig; /* ptr to original state program table */
|
||||
char *macro_def; /* macro def'n string */
|
||||
int stack_size; /* stack size */
|
||||
{
|
||||
int status;
|
||||
extern sequencer(), sprog_delete();
|
||||
extern char *seqVersion;
|
||||
int status;
|
||||
extern sequencer(), sprog_delete();
|
||||
extern char *seqVersion;
|
||||
SPROG *sp_ptr, *alloc_task_area();
|
||||
extern SPROG *seq_task_ptr;
|
||||
char *seqMacValGet(), *pname, *pvalue, *ptask_name;
|
||||
|
||||
/* If no parameters specified, print version info. */
|
||||
if (sp_ptr == 0)
|
||||
if (sp_ptr_orig == 0)
|
||||
{
|
||||
printf("%s\n", seqVersion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for correct state program format */
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
if (sp_ptr_orig->magic != MAGIC)
|
||||
{ /* Oops */
|
||||
printf("Illegal magic number in state program\n");
|
||||
logMsg("Illegal magic number in state program\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Specify a routine to run at task delete */
|
||||
if (task_area_ptr == NULL)
|
||||
{
|
||||
taskDeleteHookAdd(sprog_delete);
|
||||
task_area_ptr = (TASK *)ERROR;
|
||||
}
|
||||
|
||||
/* Specify stack size */
|
||||
if (stack_size < SPAWN_STACK_SIZE)
|
||||
stack_size = SPAWN_STACK_SIZE;
|
||||
|
||||
/* Spawn the sequencer main task */
|
||||
printf("Spawning state program \"%s\"\n", sp_ptr->name);
|
||||
status = taskSpawn(sp_ptr->name, SPAWN_PRIORITY,
|
||||
SPAWN_OPTIONS, stack_size,
|
||||
sequencer, sp_ptr, macro_def, stack_size);
|
||||
return status;
|
||||
}
|
||||
/* Sequencer main task entry point */
|
||||
sequencer(sp_ptr_orig, macro_def, stack_size)
|
||||
SPROG *sp_ptr_orig; /* ptr to original (global) state program table */
|
||||
char *macro_def; /* macro def'n string */
|
||||
int stack_size; /* stack size */
|
||||
{
|
||||
int tid, nmac, nss, nstates, nchannels, user_size;
|
||||
TASK *alloc_task_area();
|
||||
extern TASK *task_area_ptr;
|
||||
SPROG *sp_ptr;
|
||||
MACRO *mac_ptr;
|
||||
char macroTmp[100]; /* for macro names & values */
|
||||
|
||||
tid = taskIdSelf(); /* my task id */
|
||||
|
||||
/* Allocate a contiguous space for all task structures */
|
||||
task_area_ptr = alloc_task_area(sp_ptr_orig);
|
||||
#ifdef DEBUG
|
||||
printf("task_area_ptr=%d, *task_area_ptr=%d\n", task_area_ptr, *task_area_ptr);
|
||||
print_sp_info(sp_ptr_orig);
|
||||
#endif DEBUG
|
||||
|
||||
/* Make "task_area_ptr" a task variable */
|
||||
if (taskVarAdd(tid, &task_area_ptr) != OK)
|
||||
/* Specify a routine to run at task delete */
|
||||
if (seq_task_ptr == NULL)
|
||||
{
|
||||
printf("taskVarAdd failed\n");
|
||||
return -1;
|
||||
taskDeleteHookAdd(sprog_delete);
|
||||
seq_task_ptr = (SPROG *)ERROR;
|
||||
}
|
||||
|
||||
sp_ptr_orig->task_id = tid;
|
||||
sp_ptr = task_area_ptr->sp_ptr;
|
||||
mac_ptr = task_area_ptr->mac_ptr;
|
||||
|
||||
/* Allocate a contiguous space for all dynamic structures */
|
||||
sp_ptr = alloc_task_area(sp_ptr_orig);
|
||||
|
||||
/* Make a private copy of original structures (but change pointers!) */
|
||||
copy_sprog(sp_ptr_orig, task_area_ptr);
|
||||
if (sp_ptr_orig->reent_flag)
|
||||
copy_sprog(sp_ptr_orig, sp_ptr);
|
||||
|
||||
/* Initialize state program block */
|
||||
init_sprog(sp_ptr);
|
||||
@@ -122,132 +85,204 @@ int stack_size; /* stack size */
|
||||
init_sscb(sp_ptr);
|
||||
|
||||
/* Initialize the macro definition table */
|
||||
macTblInit(mac_ptr); /* Init macro table */
|
||||
seqMacTblInit(sp_ptr->mac_ptr); /* Init macro table */
|
||||
|
||||
/* Parse the macro definitions */
|
||||
macParse(macro_def, mac_ptr);
|
||||
/* Parse the macro definitions from the "program" statement */
|
||||
seqMacParse(sp_ptr->params, sp_ptr);
|
||||
|
||||
/* Connect to DB channels */
|
||||
connect_db_channels(sp_ptr, mac_ptr);
|
||||
|
||||
/* Issue monitor requests */
|
||||
issue_monitor_requests(sp_ptr);
|
||||
|
||||
/* Create the state set tasks */
|
||||
create_ss_tasks(sp_ptr, stack_size);
|
||||
|
||||
/* Note: No return from task */
|
||||
}
|
||||
/* Allocate the task area. This area will hold all state program structures:
|
||||
|***************|
|
||||
| TASK |---|
|
||||
|***************| |
|
||||
| SPROG | |
|
||||
|***************| V Ptrs to start of SPROG, SSCB[0], STATE[0],
|
||||
| SSCB [0] | USER AREA, and SCRATCH AREA
|
||||
|***************|
|
||||
| SSCB [1] |
|
||||
|***************|
|
||||
| ..... [n] |
|
||||
|***************|
|
||||
| STATE [0] |
|
||||
|***************|
|
||||
| STATE [1] |
|
||||
|***************|
|
||||
| ..... [n] |
|
||||
|***************|
|
||||
| USER AREA | - user variables (a structure)
|
||||
|***************|
|
||||
| MACRO TBL |
|
||||
|***************|
|
||||
| SCRATCH AREA | - for parsing channel names
|
||||
|***************|
|
||||
|
||||
|
||||
The pointer to the allocated area is saved for task delete hook routine.
|
||||
*/
|
||||
LOCAL TASK *alloc_task_area(sp_ptr_orig)
|
||||
SPROG *sp_ptr_orig; /* original state program area */
|
||||
{
|
||||
int size, nss, nstates, nchannels, user_size, mac_size, scr_size;
|
||||
TASK *ta_ptr; /* ptr to task area */
|
||||
|
||||
/* Calc. size of task area */
|
||||
nss = sp_ptr_orig->nss;
|
||||
nstates = count_states(sp_ptr_orig);
|
||||
nchannels = sp_ptr_orig->nchan;
|
||||
user_size = sp_ptr_orig->user_size;
|
||||
mac_size = MAX_MACROS*sizeof(MACRO);
|
||||
scr_size = SCRATCH_SIZE;
|
||||
size = sizeof(TASK) + sizeof(SPROG) + nss*sizeof(SSCB) +
|
||||
nstates*sizeof(STATE) + nchannels*sizeof(CHAN) + user_size +
|
||||
mac_size + scr_size;
|
||||
/* Parse the macro definitions from the command line */
|
||||
seqMacParse(macro_def, sp_ptr);
|
||||
#ifdef DEBUG
|
||||
printf("nss=%d, nstates=%d, nchannels=%d, user_size=%d, scr_size=%d\n",
|
||||
nss, nstates, nchannels, user_size, scr_size);
|
||||
printf("sizes: SPROG=%d, SSCB=%d, STATE=%d, CHAN=%d\n",
|
||||
sizeof(SPROG), sizeof(SSCB), sizeof(STATE), sizeof(CHAN));
|
||||
#endif DEBUG
|
||||
/* Alloc the task area & set up pointers */
|
||||
ta_ptr = (TASK *)malloc(size);
|
||||
ta_ptr->task_area_size = size;
|
||||
ta_ptr->sp_ptr = (SPROG *)(ta_ptr + 1);
|
||||
ta_ptr->ss_ptr = (SSCB *)(ta_ptr->sp_ptr+1);
|
||||
ta_ptr->st_ptr = (STATE *)(ta_ptr->ss_ptr + nss);
|
||||
ta_ptr->db_ptr = (CHAN *)(ta_ptr->st_ptr + nstates);
|
||||
ta_ptr->user_ptr = (char *)(ta_ptr->db_ptr + nchannels);
|
||||
ta_ptr->mac_ptr = (MACRO *)ta_ptr->user_ptr + user_size;
|
||||
ta_ptr->scr_ptr = (char *)ta_ptr->mac_ptr + mac_size;
|
||||
ta_ptr->scr_nleft = scr_size;
|
||||
#ifdef DEBUG
|
||||
printf("ta_ptr=%d, size=%d\n", ta_ptr, size);
|
||||
printf("sp_ptr=%d, ss_ptr=%d, st_ptr=%d, db_ptr=%d, user_ptr=%d\n",
|
||||
ta_ptr->sp_ptr, ta_ptr->ss_ptr, ta_ptr->st_ptr, ta_ptr->db_ptr, ta_ptr->user_ptr);
|
||||
printf("scr_ptr=%d, scr_nleft=%d\n", ta_ptr->scr_ptr, ta_ptr->nleft);
|
||||
print_macro_defs(sp_ptr->mac_ptr);
|
||||
#endif DEBUG
|
||||
|
||||
return ta_ptr;
|
||||
/* Initialize sequencer logging */
|
||||
seqLogInit(sp_ptr);
|
||||
|
||||
/* Specify stack size */
|
||||
pname = "stack";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), sp_ptr->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
{
|
||||
sscanf(pvalue, "%d", &stack_size);
|
||||
}
|
||||
if (stack_size < SPAWN_STACK_SIZE)
|
||||
stack_size = SPAWN_STACK_SIZE;
|
||||
|
||||
/* Specify task name */
|
||||
pname = "name";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), sp_ptr->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
ptask_name = pvalue;
|
||||
else
|
||||
ptask_name = sp_ptr->name;
|
||||
|
||||
/* Spawn the sequencer main task */
|
||||
seqLog(sp_ptr, "Spawning state program \"%s\", task name = \"%s\"\n",
|
||||
sp_ptr->name, ptask_name);
|
||||
|
||||
status = taskSpawn(ptask_name, SPAWN_PRIORITY, SPAWN_OPTIONS,
|
||||
stack_size, sequencer, sp_ptr, stack_size, ptask_name);
|
||||
seqLog(sp_ptr, " Task id = %d = 0x%x\n", status, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Count the total number of states in ALL state sets */
|
||||
LOCAL count_states(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
#ifdef DEBUG
|
||||
print_macro_defs(mac_ptr)
|
||||
MACRO *mac_ptr;
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
int nss, nstates;
|
||||
int i;
|
||||
|
||||
printf("Macro definitions:\n");
|
||||
|
||||
for (i = 0; i < MAX_MACROS; i++, mac_ptr++)
|
||||
{
|
||||
if (mac_ptr->name != NULL)
|
||||
{
|
||||
printf(" %s = %s\n", mac_ptr->name, mac_ptr->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print_sp_info(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
int nss, nstates;
|
||||
STATE *st_ptr;
|
||||
SSCB *ss_ptr;
|
||||
|
||||
printf("State Program: \"%s\"\n", sp_ptr->name);
|
||||
printf(" sp_ptr=%d=0x%x\n", sp_ptr, sp_ptr);
|
||||
printf(" sp_ptr=%d=0x%x\n", sp_ptr, sp_ptr);
|
||||
printf(" task id=%d=0x%x\n", sp_ptr->task_id, sp_ptr->task_id);
|
||||
printf(" task pri=%d\n", sp_ptr->task_priority);
|
||||
printf(" number of state sets=%d\n", sp_ptr->nss);
|
||||
printf(" number of channels=%d\n", sp_ptr->nchan);
|
||||
printf(" async flag=%d, debug flag=%d, reent flag=%d\n",
|
||||
sp_ptr->async_flag, sp_ptr->debug_flag, sp_ptr->reent_flag);
|
||||
|
||||
nstates = 0;
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
nstates += ss_ptr->num_states;
|
||||
printf(" State Set: \"%s\"\n", ss_ptr->name);
|
||||
printf(" Num states=\"%d\"\n", ss_ptr->num_states);
|
||||
printf(" State names:\n");
|
||||
st_ptr = ss_ptr->states;
|
||||
for (nstates = 0; nstates < ss_ptr->num_states; nstates++)
|
||||
{
|
||||
printf(" \"%s\"\n", st_ptr->name);
|
||||
st_ptr++;
|
||||
}
|
||||
}
|
||||
return nstates;
|
||||
return 0;
|
||||
}
|
||||
/* Copy the SPROG, SSCB, STATE, and CHAN structures into this task.
|
||||
Note: we have to change the pointers in the SPROG struct and all SSCB structs */
|
||||
LOCAL copy_sprog(sp_ptr_orig, ta_ptr)
|
||||
TASK *ta_ptr;
|
||||
SPROG *sp_ptr_orig;
|
||||
#endif DEBUG
|
||||
/* Allocate a single block for all dynamic structures. The size allocated
|
||||
will depend on whether or not the reentrant flag is set.
|
||||
The pointer to the allocated area is saved for task delete hook routine.
|
||||
*/
|
||||
LOCAL SPROG *alloc_task_area(sp_ptr_orig)
|
||||
SPROG *sp_ptr_orig; /* original state program structure */
|
||||
{
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr, *ss_ptr_orig;
|
||||
STATE *st_ptr, *st_ptr_orig;
|
||||
CHAN *db_ptr, *db_ptr_orig;
|
||||
int nss, nstates, nchan;
|
||||
int size, nss, nstates, nchannels, user_size,
|
||||
prog_size, ss_size, state_size, chan_size, mac_size, scr_size;
|
||||
SPROG *sp_ptr_new; /* ptr to new state program struct */
|
||||
char *dyn_ptr, *dyn_ptr_start; /* ptr to allocated area */
|
||||
|
||||
sp_ptr = ta_ptr->sp_ptr;
|
||||
nss = sp_ptr_orig->nss;
|
||||
nstates = sp_ptr_orig->nstates;
|
||||
nchannels = sp_ptr_orig->nchan;
|
||||
|
||||
/* Calc. # of bytes to allocate for all structures */
|
||||
prog_size = sizeof(SPROG);
|
||||
ss_size = nss*sizeof(SSCB);
|
||||
state_size = nstates*sizeof(STATE);
|
||||
chan_size = nchannels*sizeof(CHAN);
|
||||
user_size = sp_ptr_orig->user_size;
|
||||
mac_size = MAX_MACROS*sizeof(MACRO);
|
||||
scr_size = SCRATCH_SIZE;
|
||||
|
||||
/* Total # bytes to allocate */
|
||||
if (sp_ptr_orig->reent_flag)
|
||||
{
|
||||
size = prog_size + ss_size + state_size +
|
||||
chan_size + user_size + mac_size + scr_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = mac_size + scr_size;
|
||||
}
|
||||
|
||||
/* Alloc the task area */
|
||||
dyn_ptr = dyn_ptr_start = (char *)calloc(size, 1);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Allocate task area:\n");
|
||||
printf(" nss=%d, nstates=%d, nchannels=%d\n", nss, nstates, nchannels);
|
||||
printf(" prog_size=%d, ss_size=%d, state_size=%d\n",
|
||||
prog_size, ss_size, state_size);
|
||||
printf(" user_size=%d, mac_size=%d, scr_size=%d\n",
|
||||
user_size, mac_size, scr_size);
|
||||
printf(" size=%d=0x%x\n", size, size);
|
||||
printf(" dyn_ptr=%d=0x%x\n", dyn_ptr, dyn_ptr);
|
||||
#endif DEBUG
|
||||
|
||||
/* Set ptrs in the PROG structure */
|
||||
if (sp_ptr_orig->reent_flag)
|
||||
{ /* Reentry flag set: create a new structures */
|
||||
sp_ptr_new = (SPROG *)dyn_ptr;
|
||||
|
||||
/* Copy the SPROG struct contents */
|
||||
*sp_ptr_new = *sp_ptr_orig;
|
||||
|
||||
/* Allocate space for the other structures */
|
||||
dyn_ptr += prog_size;
|
||||
sp_ptr_new->sscb = (SSCB *)dyn_ptr;
|
||||
dyn_ptr += ss_size;
|
||||
sp_ptr_new->states = (STATE *)dyn_ptr;
|
||||
dyn_ptr += state_size;
|
||||
sp_ptr_new->channels = (CHAN *)dyn_ptr;
|
||||
dyn_ptr += chan_size;
|
||||
sp_ptr_new->user_area = (char *)dyn_ptr;
|
||||
dyn_ptr += user_size;
|
||||
}
|
||||
else
|
||||
{ /* Reentry flag not set: keep original structures */
|
||||
sp_ptr_new = sp_ptr_orig;
|
||||
}
|
||||
/* Create dynamic structures for macros and scratch area */
|
||||
sp_ptr_new->mac_ptr = (MACRO *)dyn_ptr;
|
||||
dyn_ptr += mac_size;
|
||||
sp_ptr_new->scr_ptr = (char *)dyn_ptr;
|
||||
sp_ptr_new->scr_nleft = scr_size;
|
||||
|
||||
/* Save ptr to allocated area so we can free it at task delete */
|
||||
sp_ptr_new->dyn_ptr = dyn_ptr_start;
|
||||
|
||||
return sp_ptr_new;
|
||||
}
|
||||
/* Copy the SSCB, STATE, and CHAN structures into this task.
|
||||
Note: we have to change the pointers in the SPROG struct, user variables,
|
||||
and all SSCB structs */
|
||||
LOCAL copy_sprog(sp_ptr_orig, sp_ptr)
|
||||
SPROG *sp_ptr_orig; /* original ptr to program struct */
|
||||
SPROG *sp_ptr; /* new ptr */
|
||||
{
|
||||
SSCB *ss_ptr, *ss_ptr_orig;
|
||||
STATE *st_ptr, *st_ptr_orig;
|
||||
CHAN *db_ptr, *db_ptr_orig;
|
||||
int nss, nstates, nchan;
|
||||
char *var_ptr;
|
||||
|
||||
/* Copy the entire SPROG struct */
|
||||
*sp_ptr = *sp_ptr_orig;
|
||||
/* Ptr to 1-st SSCB in original SPROG */
|
||||
ss_ptr_orig = sp_ptr_orig->sscb;
|
||||
|
||||
/* Ptr to 1-st SSCB in new SPROG */
|
||||
ss_ptr = ta_ptr->ss_ptr;
|
||||
sp_ptr->sscb = ss_ptr; /* Fix ptr to 1-st SSCB */
|
||||
st_ptr = ta_ptr->st_ptr;
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
|
||||
/* Copy structures for each state set */
|
||||
st_ptr = sp_ptr->states;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++)
|
||||
{
|
||||
*ss_ptr = *ss_ptr_orig; /* copy SSCB */
|
||||
@@ -255,33 +290,47 @@ SPROG *sp_ptr_orig;
|
||||
st_ptr_orig = ss_ptr_orig->states;
|
||||
for (nstates = 0; nstates < ss_ptr->num_states; nstates++)
|
||||
{
|
||||
*st_ptr++ = *st_ptr_orig++; /* copy STATE struct */
|
||||
*st_ptr = *st_ptr_orig; /* copy STATE struct */
|
||||
st_ptr++;
|
||||
st_ptr_orig++;
|
||||
}
|
||||
ss_ptr++;
|
||||
ss_ptr_orig++;
|
||||
}
|
||||
|
||||
/* Copy database channel structures */
|
||||
db_ptr = ta_ptr->db_ptr;
|
||||
sp_ptr->channels = db_ptr;
|
||||
db_ptr = sp_ptr->channels;
|
||||
db_ptr_orig = sp_ptr_orig->channels;
|
||||
var_ptr = sp_ptr->user_area;
|
||||
for (nchan = 0; nchan < sp_ptr->nchan; nchan++)
|
||||
{
|
||||
*db_ptr = *db_ptr_orig;
|
||||
|
||||
/* Reset ptr to SPROG structure */
|
||||
db_ptr->sprog = sp_ptr;
|
||||
|
||||
/* Convert offset to address of the user variable */
|
||||
db_ptr->var += (int)var_ptr;
|
||||
|
||||
db_ptr++;
|
||||
db_ptr_orig++;
|
||||
}
|
||||
|
||||
/* Note: user area is not copied; it should be all zeros */
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Initialize state program block */
|
||||
LOCAL init_sprog(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
/* Semaphore for resource locking on events */
|
||||
sp_ptr->sem_id = semCreate();
|
||||
semInit(sp_ptr->sem_id);
|
||||
semGive(sp_ptr->sem_id);
|
||||
|
||||
sp_ptr->task_is_deleted = FALSE;
|
||||
sp_ptr->logFd = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -291,130 +340,105 @@ LOCAL init_sscb(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
int nss;
|
||||
char task_name[20];
|
||||
int nss, i;
|
||||
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
st_ptr = ss_ptr->states; /* 1-st state */
|
||||
ss_ptr->task_id = 0;
|
||||
ss_ptr->sem_id = semCreate();
|
||||
semInit(ss_ptr->sem_id);
|
||||
semGive(ss_ptr->sem_id);
|
||||
ss_ptr->ev_flag = 0;
|
||||
ss_ptr->ev_flag_mask = st_ptr->event_flag_mask;
|
||||
ss_ptr->current_state = st_ptr; /* initial state */
|
||||
ss_ptr->next_state = NULL;
|
||||
ss_ptr->current_state = 0; /* initial state */
|
||||
ss_ptr->next_state = 0;
|
||||
ss_ptr->action_complete = TRUE;
|
||||
for (i = 0; i < NWRDS; i++)
|
||||
ss_ptr->events[i] = 0; /* clear events */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Get DB value (uses channel access) */
|
||||
seq_pvGet(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
ca_array_get(db_ptr->dbr_type, db_ptr->count, db_ptr->chid, db_ptr->var);
|
||||
/********** In this version we wait for each db_get() **********/
|
||||
status = ca_pend_io(10.0);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
printf("time-out: db_get() on %s\n", db_ptr->db_name);
|
||||
return -1;
|
||||
}
|
||||
/********** We should have an event handler for this call ************/
|
||||
/********** Then we could use event flags on "db_get" calls **********/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Put DB value (uses channel access) */
|
||||
seq_pvPut(sp_ptr, ss_ptr, db_ptr)
|
||||
SPROG *sp_ptr; /* ptr to state program */
|
||||
SSCB *ss_ptr; /* ptr to current state set */
|
||||
CHAN *db_ptr; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
status = ca_array_put(db_ptr->dbr_type, db_ptr->count,
|
||||
db_ptr->chid, db_ptr->var);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_array_put");
|
||||
return -1;
|
||||
}
|
||||
ca_flush_io();
|
||||
}
|
||||
/* Set event flag bits for each state set */
|
||||
seq_efSet(sp_ptr, ss_ptr, ev_flag)
|
||||
SPROG *sp_ptr; /* state program where ev flags are to be set */
|
||||
SSCB *ss_ptr; /* not currently used */
|
||||
int ev_flag; /* bits to set */
|
||||
{
|
||||
int nss;
|
||||
SSCB *ssp;
|
||||
EVFLAG ev_flag_chk;
|
||||
|
||||
#ifdef DEBUG
|
||||
char *name;
|
||||
name = "?";
|
||||
if (ss_ptr != NULL)
|
||||
name = ss_ptr->name;
|
||||
printf("seq_efSet: bits 0x%x from ss %s\n", ev_flag, name);
|
||||
#endif
|
||||
|
||||
ssp = sp_ptr->sscb; /* 1-st state set */
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ssp++)
|
||||
{ /********** need some resource locking here ***************/
|
||||
/* Set event flag only if "action" is complete */
|
||||
if (ssp->action_complete)
|
||||
{ /* Only set ev flag if contained in mask & bit(s) get set */
|
||||
ev_flag_chk = (ev_flag & ssp->ev_flag_mask) | ssp->ev_flag;
|
||||
if (ev_flag_chk != ssp->ev_flag) /* did bit get set? */
|
||||
{ /* set the bit(s) & wake up the ss task */
|
||||
ssp->ev_flag = ev_flag_chk;
|
||||
semGive(ssp->sem_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test event flag for matching bits */
|
||||
seq_efTest(sp_ptr, ss_ptr, ev_flag)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
int ev_flag; /* bit(s) to test */
|
||||
{
|
||||
int nss;
|
||||
SSCB *ssp;
|
||||
|
||||
if ( (ss_ptr->ev_flag & ev_flag) != 0 )
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Allocate memory from scratch area (always round up to even no. bytes) */
|
||||
char *seqAlloc(nChar)
|
||||
char *seqAlloc(sp_ptr, nChar)
|
||||
SPROG *sp_ptr;
|
||||
int nChar;
|
||||
{
|
||||
char *pStr;
|
||||
extern TASK *task_area_ptr;
|
||||
|
||||
pStr = task_area_ptr->scr_ptr;
|
||||
pStr = sp_ptr->scr_ptr;
|
||||
/* round to even no. bytes */
|
||||
if ((nChar & 1) != 0)
|
||||
nChar++;
|
||||
if (task_area_ptr->scr_nleft >= nChar)
|
||||
if (sp_ptr->scr_nleft >= nChar)
|
||||
{
|
||||
task_area_ptr->scr_ptr += nChar;
|
||||
task_area_ptr->scr_nleft -= nChar;
|
||||
sp_ptr->scr_ptr += nChar;
|
||||
sp_ptr->scr_nleft -= nChar;
|
||||
return pStr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
/* Initialize logging */
|
||||
seqLogInit(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
char *pname, *pvalue, *seqMacValGet();
|
||||
int fd;
|
||||
|
||||
/* Create a resource locking semaphore */
|
||||
sp_ptr->logSemId = semCreate();
|
||||
semInit(sp_ptr->logSemId);
|
||||
semGive(sp_ptr->logSemId);
|
||||
|
||||
sp_ptr->logFd = ioGlobalStdGet(1); /* default fd is std out */
|
||||
|
||||
/* Check for logfile spec. */
|
||||
pname = "logfile";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), sp_ptr->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
{ /* Create & open file for write only */
|
||||
fd = open(pvalue, O_CREAT | O_WRONLY, 0664);
|
||||
if (fd != ERROR)
|
||||
sp_ptr->logFd = fd;
|
||||
printf("logfile=%s, fd=%d\n", pvalue, fd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Log a message to the console or a file with time of day and task id */
|
||||
#include "tsDefs.h"
|
||||
seqLog(sp_ptr, fmt, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
SPROG *sp_ptr;
|
||||
char *fmt; /* format string */
|
||||
int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */
|
||||
{
|
||||
int fd;
|
||||
TS_STAMP timeStamp;
|
||||
char timeBfr[28];
|
||||
|
||||
/* Get time of day */
|
||||
tsLocalTime(&timeStamp); /* time stamp format */
|
||||
|
||||
/* Convert to mm/dd/yy hh:mm:ss.nano-sec */
|
||||
tsStampToText(&timeStamp, TS_TEXT_MMDDYY, timeBfr);
|
||||
/* Truncate the .nano-secs part */
|
||||
timeBfr[17] = 0;
|
||||
|
||||
/* Lock seqLog resource */
|
||||
semTake(sp_ptr->logSemId, 0);
|
||||
|
||||
/* Print the message: e.g. "10:23:28 T13: ...." */
|
||||
fd = sp_ptr->logFd;
|
||||
fdprintf(fd, "%s %s: ", taskName(taskIdSelf()), &timeBfr[9]);
|
||||
fdprintf(fd, fmt, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
|
||||
/* Unlock the resource */
|
||||
semGive(sp_ptr->logSemId);
|
||||
|
||||
/* If NSF file then flush the buffer */
|
||||
if (fd != ioGlobalStdGet(1) )
|
||||
{
|
||||
ioctl(fd, FIOSYNC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_qry.c 1.3 11/9/90
|
||||
@(#)seq_qry.c 1.4 4/17/91
|
||||
DESCRIPTION: Task querry & debug routines for run-time sequencer
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
@@ -15,71 +15,136 @@
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
|
||||
/* querry the sequencer */
|
||||
seqQry(tid)
|
||||
/* Querry the sequencer for state information */
|
||||
seqShow(tid)
|
||||
int tid;
|
||||
{
|
||||
extern TASK *task_area_ptr;
|
||||
TASK *ta_ptr;
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
CHAN *db_ptr;
|
||||
int nss, nst, nch;
|
||||
float time;
|
||||
extern SPROG *seq_task_ptr;
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
CHAN *db_ptr;
|
||||
int nss, nst, nch;
|
||||
float time;
|
||||
|
||||
/* Info? */
|
||||
if (tid == 0)
|
||||
{
|
||||
printf("Usage: seqShow <task id>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the seq_task_ptr (it's task variable) */
|
||||
sp_ptr = (SPROG *)taskVarGet(tid, &seq_task_ptr);
|
||||
|
||||
ta_ptr = (TASK *)taskVarGet(tid, &task_area_ptr); /* task_area_ptr is task variable */
|
||||
sp_ptr = ta_ptr->sp_ptr;
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
{
|
||||
printf("tqry: wrong magic number\n");
|
||||
printf("seqShow: wrong magic number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Print info about state program */
|
||||
printf("State Program: \"%s\"\n", sp_ptr->name);
|
||||
printf(" ta_ptr=%d=0x%x\n", ta_ptr, ta_ptr);
|
||||
printf(" sp_ptr=%d=0x%x\n", sp_ptr, sp_ptr);
|
||||
printf(" initial task id=%d=0x%x\n", sp_ptr->task_id, sp_ptr->task_id);
|
||||
printf(" task priority=%d\n", sp_ptr->task_priority);
|
||||
printf(" number of state sets=%d\n", sp_ptr->nss);
|
||||
printf(" number of channels=%d\n", sp_ptr->nchan);
|
||||
printf(" async flag=%d, debug flag=%d, reent flag=%d, conn flag=%d\n",
|
||||
sp_ptr->async_flag, sp_ptr->debug_flag, sp_ptr->reent_flag, sp_ptr->conn_flag);
|
||||
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
printf(" State Set: \"%s\"\n", ss_ptr->name);
|
||||
printf("\tss_ptr=%d=0x%x\n", ss_ptr, ss_ptr);
|
||||
st_ptr = ss_ptr->current_state;
|
||||
if (st_ptr != NULL) {
|
||||
printf("\tcurrent state: \"%s\"\n", st_ptr->name);
|
||||
}
|
||||
time = ss_ptr->time/60.0;
|
||||
printf("\ttime state was entered=%d tics (%g seconds)\n",
|
||||
ss_ptr->time, time);
|
||||
st_ptr = ss_ptr->next_state;
|
||||
printf("\tevent flag=%d\n", ss_ptr->ev_flag);
|
||||
printf("\tevent flag mask=0x%x\n", ss_ptr->ev_flag_mask);
|
||||
printf("\tnumer delays queued=%d\n", ss_ptr->ndelay);
|
||||
if (st_ptr != NULL)
|
||||
printf("\tnext state: \"%s\"\n", st_ptr->name);
|
||||
}
|
||||
wait_rtn();
|
||||
|
||||
/* Print info about db channels */
|
||||
db_ptr = sp_ptr->channels;
|
||||
for (nch = 0; nch < sp_ptr->nchan; nch++, db_ptr++)
|
||||
{
|
||||
printf("\nChannel name: \"%s\"\n", db_ptr->db_name);
|
||||
printf(" unexpanded name: \"%s\"\n", db_ptr->db_uname);
|
||||
printf(" size=%d bytes\n", db_ptr->size);
|
||||
printf(" length=%d elements\n", db_ptr->length);
|
||||
printf(" DB request type=%d\n", db_ptr->dbr_type);
|
||||
printf(" monitor flag=%d\n", db_ptr->mon_flag);
|
||||
printf(" count=%d\n", db_ptr->count);
|
||||
printf(" event flag=%d=0x%x\n", db_ptr->ev_flag, db_ptr->ev_flag);
|
||||
printf(" delta=%g\n", db_ptr->delta);
|
||||
printf(" timeout=%g\n", db_ptr->timeout);
|
||||
printf(" task id=%d=0x%x\n", ss_ptr->task_id, ss_ptr->task_id);
|
||||
|
||||
st_ptr = ss_ptr->states;
|
||||
printf(" First state = \"%s\"\n", ss_ptr->states->name);
|
||||
|
||||
st_ptr = ss_ptr->states + ss_ptr->current_state;
|
||||
printf(" Current state = \"%s\"\n", st_ptr->name);
|
||||
|
||||
st_ptr = ss_ptr->states + ss_ptr->prev_state;
|
||||
printf(" Previous state = \"%s\"\n", st_ptr->name);
|
||||
|
||||
time = (tickGet() - ss_ptr->time)/60.0;
|
||||
printf("\tTime since state was entered = %.1f seconds)\n", time);
|
||||
|
||||
printf("\tNumber delays queued=%d\n", ss_ptr->ndelay);
|
||||
|
||||
wait_rtn();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Querry the sequencer for channel information */
|
||||
seqChanShow(tid)
|
||||
int tid;
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
SPROG *sp_ptr;
|
||||
CHAN *db_ptr;
|
||||
int nch;
|
||||
float time;
|
||||
|
||||
/* Info? */
|
||||
if (tid == 0)
|
||||
{
|
||||
printf("Usage: seqChanShow <task id>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp_ptr = (SPROG *)taskVarGet(tid, &seq_task_ptr); /* seq_task_ptr is task variable */
|
||||
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
{
|
||||
printf("seqChanQry: wrong magic number\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
db_ptr = sp_ptr->channels;
|
||||
printf("State Program: \"%s\"\n", sp_ptr->name);
|
||||
printf("Number of channels=%d\n", sp_ptr->nchan);
|
||||
|
||||
for (nch = 0; nch < sp_ptr->nchan; nch++, db_ptr++)
|
||||
{
|
||||
printf("\nChannel name: \"%s\"\n", db_ptr->db_name);
|
||||
printf(" Unexpanded name: \"%s\"\n", db_ptr->db_uname);
|
||||
printf(" Variable=%d=0x%x\n", db_ptr->var, db_ptr->var);
|
||||
printf(" Size=%d bytes\n", db_ptr->size);
|
||||
printf(" Count=%d\n", db_ptr->count);
|
||||
printf(" DB get request type=%d\n", db_ptr->get_type);
|
||||
printf(" DB put request type=%d\n", db_ptr->put_type);
|
||||
printf(" monitor flag=%d\n", db_ptr->mon_flag);
|
||||
|
||||
if (db_ptr->monitored)
|
||||
printf(" Monitored\n");
|
||||
else
|
||||
printf(" Not monitored\n");
|
||||
|
||||
if(db_ptr->connected)
|
||||
printf(" Connected\n");
|
||||
else
|
||||
printf(" Not connected\n");
|
||||
|
||||
if(db_ptr->get_complete)
|
||||
printf(" Last get completed\n");
|
||||
else
|
||||
printf(" Get not completed\n");
|
||||
|
||||
printf(" Status=%d\n", db_ptr->status);
|
||||
printf(" Severity=%d\n", db_ptr->severity);
|
||||
|
||||
printf(" Delta=%g\n", db_ptr->delta);
|
||||
printf(" Timeout=%g\n", db_ptr->timeout);
|
||||
wait_rtn();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
wait_rtn()
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_task.c 1.4 2/1/91
|
||||
@(#)seq_task.c 1.7 4/23/91
|
||||
DESCRIPTION: Seq_tasks.c: Task creation and control for sequencer
|
||||
state sets.
|
||||
|
||||
@@ -14,50 +14,63 @@
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
|
||||
|
||||
LOCAL ss_task_init();
|
||||
LOCAL ULONG get_timeout();
|
||||
LOCAL VOID semTake();
|
||||
|
||||
|
||||
extern TASK *task_area_ptr;
|
||||
|
||||
/* Create state set tasks. Set task variable for each task */
|
||||
#define TASK_NAME_SIZE 25
|
||||
create_ss_tasks(sp_ptr, stack_size)
|
||||
SPROG *sp_ptr;
|
||||
int stack_size;
|
||||
#define TASK_NAME_SIZE 10
|
||||
/* Sequencer main task entry point */
|
||||
sequencer(sp_ptr, stack_size, ptask_name)
|
||||
SPROG *sp_ptr; /* ptr to original (global) state program table */
|
||||
int stack_size; /* stack size */
|
||||
char *ptask_name; /* Parent task name */
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
int nss;
|
||||
char task_name[2*TASK_NAME_SIZE+2];
|
||||
extern TASK *task_area_ptr;
|
||||
extern ss_entry();
|
||||
extern SPROG *seq_task_ptr;
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
int nss, task_id;
|
||||
char task_name[TASK_NAME_SIZE+10];
|
||||
extern ss_entry();
|
||||
|
||||
sp_ptr->task_id = taskIdSelf(); /* my task id */
|
||||
|
||||
/* Make "seq_task_ptr" a task variable */
|
||||
if (taskVarAdd(sp_ptr->task_id, &seq_task_ptr) != OK)
|
||||
{
|
||||
seqLog(sp_ptr, "%s: taskVarAdd failed\n", sp_ptr->name);
|
||||
return -1;
|
||||
}
|
||||
seq_task_ptr = sp_ptr;
|
||||
|
||||
/* Initilaize state set to first task, and set event mask */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
task_name[0] = 0;
|
||||
strncat(task_name, sp_ptr->name, TASK_NAME_SIZE);
|
||||
strcat(task_name, "_");
|
||||
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
if (nss != 0)
|
||||
{ /* Spawn the ss task */
|
||||
/* Form task name from program name + state set name */
|
||||
strncat(task_name, ss_ptr->name, TASK_NAME_SIZE);
|
||||
|
||||
ss_ptr->task_id = taskSpawn(task_name,
|
||||
SPAWN_PRIORITY+ss_ptr->task_priority,
|
||||
SPAWN_OPTIONS, stack_size, ss_entry, sp_ptr, ss_ptr);
|
||||
#ifdef DEBUG
|
||||
printf("task %d: %s\n", ss_ptr->task_id, task_name);
|
||||
#endif DEBUG
|
||||
}
|
||||
st_ptr = ss_ptr->states;
|
||||
ss_ptr->current_state = 0;
|
||||
ss_ptr->pMask = (st_ptr->eventMask);
|
||||
}
|
||||
|
||||
/* Connect to database channels & initiate monitor requests.
|
||||
Returns here immediately if "connect" switch is not set */
|
||||
connect_db_channels(sp_ptr);
|
||||
|
||||
/* Create the state set tasks */
|
||||
if (strlen(ptask_name) > TASK_NAME_SIZE);
|
||||
ptask_name[TASK_NAME_SIZE] = 0;
|
||||
|
||||
ss_ptr = sp_ptr->sscb + 1;
|
||||
for (nss = 1; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
/* Form task name from program name + state set number */
|
||||
sprintf(task_name, "%s_%d", ptask_name, nss);
|
||||
|
||||
/* Spawn the task */
|
||||
task_id = taskSpawn(task_name,
|
||||
SPAWN_PRIORITY+ss_ptr->task_priority,
|
||||
SPAWN_OPTIONS, stack_size, ss_entry, sp_ptr, ss_ptr);
|
||||
|
||||
seqLog(sp_ptr, "Spawning task %d: \"%s\"\n", task_id, task_name);
|
||||
}
|
||||
|
||||
/* Main task handles first state set */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
ss_ptr->task_id = sp_ptr->task_id;
|
||||
ss_entry(sp_ptr, ss_ptr);
|
||||
ss_entry(sp_ptr, sp_ptr->sscb);
|
||||
}
|
||||
/* Task entry point for state sets */
|
||||
/* Provides main loop for state set processing (common, re-entrant code) */
|
||||
@@ -65,32 +78,28 @@ ss_entry(sp_ptr, ss_ptr)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
{
|
||||
BOOL ev_trig;
|
||||
STATE *st_ptr;
|
||||
ULONG delay, get_timeout();
|
||||
BOOL ev_trig;
|
||||
STATE *st_ptr, *st_pNext;
|
||||
ULONG delay, get_timeout();
|
||||
int i;
|
||||
char *var_ptr;
|
||||
|
||||
/* Initialize all tasks except the main task */
|
||||
ss_ptr->task_id = taskIdSelf();
|
||||
if (ss_ptr->task_id != sp_ptr->task_id)
|
||||
ss_task_init(sp_ptr, ss_ptr);
|
||||
|
||||
/* Start in first state */
|
||||
st_ptr = ss_ptr->current_state;
|
||||
|
||||
/* Initialize for event flag processing */
|
||||
ss_ptr->ev_flag_mask = st_ptr->event_flag_mask;
|
||||
ss_ptr->ev_flag = 0;
|
||||
var_ptr = sp_ptr->user_area;
|
||||
st_ptr = ss_ptr->states;
|
||||
|
||||
/* Main loop */
|
||||
while (1)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("State set %s, state %s\n", ss_ptr->name, st_ptr->name);
|
||||
#endif DEBUG
|
||||
ss_ptr->time = tickGet(); /* record time we entered this state */
|
||||
|
||||
/* Call delay function to set up delays */
|
||||
ss_ptr->ndelay = 0;
|
||||
st_ptr->delay_func(sp_ptr, ss_ptr);
|
||||
st_ptr->delay_func(sp_ptr, ss_ptr, var_ptr);
|
||||
|
||||
/* On 1-st pass fall thru w/o wake up */
|
||||
semGive(ss_ptr->sem_id);
|
||||
@@ -100,23 +109,45 @@ SSCB *ss_ptr;
|
||||
/* Wake up on CA event, event flag, or expired time delay */
|
||||
semTake(ss_ptr->sem_id, get_timeout(ss_ptr, st_ptr));
|
||||
#ifdef DEBUG
|
||||
printf("%s: semTake returned\n", ss_ptr->name);
|
||||
printf("%s: semTake returned, events[0]=0x%x\n",
|
||||
ss_ptr->name, ss_ptr->events[0]);
|
||||
#endif DEBUG
|
||||
ss_ptr->time = tickGet();
|
||||
/* Call event function to check for event trigger */
|
||||
ev_trig = st_ptr->event_func(sp_ptr, ss_ptr);
|
||||
} while (!ev_trig);
|
||||
|
||||
/* Event triggered, execute the corresponding action */
|
||||
/* Apply resource lock: any new events coming in will
|
||||
be deferred until next state is entered */
|
||||
semTake(sp_ptr->sem_id, 0);
|
||||
|
||||
/* Call event function to check for event trigger */
|
||||
ev_trig = st_ptr->event_func(sp_ptr, ss_ptr, var_ptr);
|
||||
|
||||
if (!ev_trig)
|
||||
semGive(sp_ptr->sem_id); /* Unlock resource */
|
||||
} while (!ev_trig);
|
||||
/* Event triggered */
|
||||
|
||||
/* Change event mask ptr for next state */
|
||||
st_pNext = ss_ptr->states + ss_ptr->next_state;
|
||||
ss_ptr->pMask = (st_pNext->eventMask);
|
||||
|
||||
/* Clear event bits */
|
||||
for (i = 0; i < NWRDS; i++)
|
||||
ss_ptr->events[i] = 0;
|
||||
|
||||
/* Unlock resource */
|
||||
semGive(sp_ptr->sem_id);
|
||||
|
||||
/* Execute the action for this event */
|
||||
ss_ptr->action_complete = FALSE;
|
||||
st_ptr->action_func(sp_ptr, ss_ptr);
|
||||
st_ptr->action_func(sp_ptr, ss_ptr, var_ptr);
|
||||
|
||||
/* Flush any outstanding DB requests */
|
||||
ca_flush_io();
|
||||
|
||||
/* Change to next state */
|
||||
ss_ptr->prev_state = ss_ptr->current_state;
|
||||
ss_ptr->current_state = ss_ptr->next_state;
|
||||
ss_ptr->next_state = NULL;
|
||||
st_ptr = ss_ptr->current_state;
|
||||
ss_ptr->ev_flag_mask = st_ptr->event_flag_mask;
|
||||
ss_ptr->ev_flag = 0;
|
||||
st_ptr = ss_ptr->states + ss_ptr->current_state;
|
||||
ss_ptr->action_complete = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -125,9 +156,12 @@ LOCAL ss_task_init(sp_ptr, ss_ptr)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
{
|
||||
extern SPROG *seq_task_ptr;
|
||||
|
||||
|
||||
/* Import task variable context from main task */
|
||||
taskVarAdd(ss_ptr->task_id, &task_area_ptr);
|
||||
taskVarGet(sp_ptr->task_id, &task_area_ptr); /* main task's id */
|
||||
taskVarAdd(ss_ptr->task_id, &seq_task_ptr);
|
||||
seq_task_ptr = sp_ptr;
|
||||
|
||||
/* Import Channel Access context from main task */
|
||||
ca_import(sp_ptr->task_id);
|
||||
@@ -168,7 +202,12 @@ SSCB *ss_ptr;
|
||||
int delay_id; /* delay id */
|
||||
float delay;
|
||||
{
|
||||
ss_ptr->timeout[delay_id] = ss_ptr->time + delay*60.0;
|
||||
int td_tics;
|
||||
|
||||
/* Note: the following 2 lines could be combined, but doing so produces
|
||||
* the undefined symbol "Mund", which is not in VxWorks library */
|
||||
td_tics = delay*60.0;
|
||||
ss_ptr->timeout[delay_id] = ss_ptr->time + td_tics;
|
||||
delay_id += 1;
|
||||
if (delay_id > ss_ptr->ndelay)
|
||||
ss_ptr->ndelay = delay_id;
|
||||
@@ -187,49 +226,79 @@ int delay_id;
|
||||
sprog_delete(pTcbX)
|
||||
TCBX *pTcbX; /* ptr to TCB of task to be deleted */
|
||||
{
|
||||
int tid, nss, val, tid_ss;
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
extern TASK *task_area_ptr;
|
||||
TASK *ta_ptr;
|
||||
int tid, nss, val, tid_ss;
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
extern SPROG *seq_task_ptr;
|
||||
|
||||
tid = pTcbX->taskId;
|
||||
/* Note: task_area_ptr is a task variable */
|
||||
val = taskVarGet(tid, &task_area_ptr);
|
||||
/* Note: seq_task_ptr is a task variable */
|
||||
val = taskVarGet(tid, &seq_task_ptr);
|
||||
if (val == ERROR)
|
||||
return 0; /* not one of our tasks */
|
||||
ta_ptr = (TASK *)val;
|
||||
printf(" ta_ptr=0x%x, tid=%d=0x%x\n", ta_ptr, tid, tid);
|
||||
sp_ptr = ta_ptr->sp_ptr;
|
||||
sp_ptr = (SPROG *)val;
|
||||
logMsg("Delete %s: sp_ptr=%d=0x%x, tid=%d\n",
|
||||
sp_ptr->name, sp_ptr, sp_ptr, tid);
|
||||
|
||||
/* Is this a real sequencer task? */
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
{
|
||||
printf(" Not main state program task\n");
|
||||
logMsg(" Not main state program task\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Delete state set tasks */
|
||||
/* Suspend state set tasks */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
tid_ss = ss_ptr->task_id;
|
||||
if ( tid_ss > 0)
|
||||
{
|
||||
/* Don't delete self yet */
|
||||
/* Don't suspend self */
|
||||
if (tid != tid_ss)
|
||||
{
|
||||
printf(" delete ss task: tid=%d=0x%x\n",
|
||||
tid_ss, tid_ss);
|
||||
taskVarSet(tid_ss, &task_area_ptr, ERROR);
|
||||
taskDelete(tid_ss);
|
||||
logMsg(" suspend ss task: tid=%d\n", tid_ss);
|
||||
taskVarSet(tid_ss, &seq_task_ptr, ERROR);
|
||||
taskSuspend(tid_ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("free ta_ptr=0x%x\n", ta_ptr);
|
||||
taskDelay(60);
|
||||
free(ta_ptr);
|
||||
/* Call user exit routine */
|
||||
sp_ptr->exit_func(sp_ptr, sp_ptr->user_area);
|
||||
|
||||
/* Close the log file */
|
||||
if (sp_ptr->logFd > 0 && sp_ptr->logFd != ioGlobalStdGet(1))
|
||||
{
|
||||
logMsg("Closing log fd=%d\n", sp_ptr->logFd);
|
||||
close(sp_ptr->logFd);
|
||||
sp_ptr->logFd = ioGlobalStdGet(1);
|
||||
}
|
||||
|
||||
/* Delete state set tasks & delete semaphores */
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
tid_ss = ss_ptr->task_id;
|
||||
if ( tid_ss > 0)
|
||||
{
|
||||
/* Don't delete self */
|
||||
if (tid != tid_ss)
|
||||
{
|
||||
logMsg(" delete ss task: tid=%d\n", tid_ss);
|
||||
taskVarSet(tid_ss, &seq_task_ptr, ERROR);
|
||||
taskDelete(tid_ss);
|
||||
}
|
||||
semDelete(ss_ptr->sem_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete semaphores & free the task area */
|
||||
semDelete(sp_ptr->sem_id);
|
||||
semDelete(sp_ptr->logSemId);
|
||||
logMsg("free sp_ptr->dyn_ptr=0x%x\n", sp_ptr->dyn_ptr);
|
||||
taskDelay(5);
|
||||
free(sp_ptr->dyn_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)snc.y 1.1 10/16/90
|
||||
@(#)snc.y 1.2 4/17/91
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
/* SNC - State Notation Compiler.
|
||||
@@ -31,9 +31,6 @@
|
||||
#include <ctype.h>
|
||||
#include "parse.h"
|
||||
|
||||
Expr *expression();
|
||||
Expr *parameter();
|
||||
|
||||
extern int line_num; /* input file line no. */
|
||||
%}
|
||||
|
||||
@@ -44,27 +41,33 @@ extern int line_num; /* input file line no. */
|
||||
int ival;
|
||||
char *pchar;
|
||||
void *pval;
|
||||
Expr *expr;
|
||||
Expr *pexpr;
|
||||
}
|
||||
%token <pchar> STATE STATE_SET
|
||||
%token <pchar> NUMBER NAME DBNAME
|
||||
%token <pchar> NUMBER NAME
|
||||
%token <pchar> DEBUG_PRINT
|
||||
%token PROGRAM DEFINE
|
||||
%token PROGRAM EXIT
|
||||
%token R_SQ_BRACKET L_SQ_BRACKET
|
||||
%token BAD_CHAR L_BRACKET R_BRACKET
|
||||
%token COLON SEMI_COLON EQUAL
|
||||
%token L_PAREN R_PAREN PERIOD COMMA OR AND
|
||||
%token MONITOR ASSIGN TO WHEN INT FLOAT DOUBLE SHORT CHAR STRING_DECL
|
||||
%token MONITOR ASSIGN TO WHEN CHAR SHORT INT LONG FLOAT DOUBLE STRING_DECL
|
||||
%token EVFLAG SYNC
|
||||
%token ASTERISK AMPERSAND
|
||||
%token PLUS MINUS SLASH GT GE EQ LE LT NE NOT
|
||||
%token PLUS MINUS SLASH GT GE EQ LE LT NE NOT BIT_OR BIT_AND
|
||||
%token L_SHIFT R_SHIFT COMPLEMENT MODULO
|
||||
%token PLUS_EQUAL MINUS_EQUAL MULT_EQUAL DIV_EQUAL AND_EQUAL OR_EQUAL
|
||||
%token MODULO_EQUAL LEFT_EQUAL RIGHT_EQUAL CMPL_EQUAL
|
||||
%token <pchar> STRING
|
||||
%token <pchar> C_STMT
|
||||
%token IF ELSE WHILE
|
||||
%token PP_SYMBOL CR
|
||||
%type <ival> type
|
||||
%type <pchar> subscript
|
||||
%type <expr> parameter function expression
|
||||
/* precidence rules for expression evaluation */
|
||||
%type <pchar> subscript binop asgnop unop
|
||||
%type <pexpr> state_set_list state_set state_list state transition_list transition
|
||||
%type <pexpr> parameter expr
|
||||
%type <pexpr> statement stmt_list compound_stmt if_stmt else_stmt while_stmt
|
||||
/* precidence rules for expr evaluation */
|
||||
%left OR AND
|
||||
%left GT GE EQ NE LE LT
|
||||
%left PLUS MINUS
|
||||
@@ -75,9 +78,11 @@ extern int line_num; /* input file line no. */
|
||||
%% /* Begin rules */
|
||||
|
||||
state_program /* define a state program */
|
||||
: program_name definitions program_body { program(""); }
|
||||
| program_name definitions program_body C_STMT { program($4); }
|
||||
| error { snc_err("state program", line_num, 12); }
|
||||
: program_name definitions state_set_list { program($3); }
|
||||
| program_name definitions state_set_list global_c { program($3); }
|
||||
| pp_code program_name definitions state_set_list { program($4); }
|
||||
| pp_code program_name definitions state_set_list global_c{ program($4); }
|
||||
| error { snc_err("state program"); }
|
||||
;
|
||||
|
||||
program_name /* program name */
|
||||
@@ -97,21 +102,17 @@ defn_stmt /* individual definitions for SNL (preceeds state sets) */
|
||||
| debug_stmt
|
||||
| sync_stmt
|
||||
| C_STMT { defn_c_stmt($1); }
|
||||
| error { snc_err("definitions", line_num, 1); }
|
||||
| pp_code
|
||||
| error { snc_err("definitions/declarations"); }
|
||||
;
|
||||
|
||||
assign_stmt /* 'assign <var name>[<lower lim>,<upper lim>] to <db name>;' */
|
||||
/* subscript range is optional */
|
||||
: ASSIGN NAME TO STRING SEMI_COLON { assign_stmt($2, (char *)0, (char *)0, $4); }
|
||||
| ASSIGN NAME L_SQ_BRACKET NUMBER R_SQ_BRACKET TO STRING SEMI_COLON
|
||||
{ assign_stmt($2, $4, (char *)0, $7); }
|
||||
| ASSIGN NAME L_SQ_BRACKET NUMBER COMMA NUMBER R_SQ_BRACKET TO STRING SEMI_COLON
|
||||
{ assign_stmt($2, $4, $6, $9); }
|
||||
assign_stmt /* 'assign <var name> to <db name>;' */
|
||||
: ASSIGN NAME TO STRING SEMI_COLON { assign_stmt($2, $4); }
|
||||
;
|
||||
|
||||
monitor_stmt /* variable to be monitored; subscript & delta are optional */
|
||||
: MONITOR NAME subscript SEMI_COLON { monitor_stmt($2, $3, "0"); }
|
||||
| MONITOR NAME subscript COMMA NUMBER SEMI_COLON { monitor_stmt($2, $3, $5); }
|
||||
monitor_stmt /* variable to be monitored; delta is optional */
|
||||
: MONITOR NAME SEMI_COLON { monitor_stmt($2, "0"); }
|
||||
| MONITOR NAME COMMA NUMBER SEMI_COLON { monitor_stmt($2, $4); }
|
||||
;
|
||||
|
||||
subscript /* e.g. [10] */
|
||||
@@ -130,110 +131,164 @@ decl_stmt /* variable declarations (e.g. float x[20];) */
|
||||
;
|
||||
|
||||
type /* types for variables defined in SNL */
|
||||
: FLOAT { $$ = V_FLOAT; }
|
||||
| DOUBLE { $$ = V_DOUBLE; }
|
||||
| INT { $$ = V_INT; }
|
||||
: CHAR { $$ = V_CHAR; }
|
||||
| SHORT { $$ = V_SHORT; }
|
||||
| CHAR { $$ = V_CHAR; }
|
||||
| INT { $$ = V_INT; }
|
||||
| LONG { $$ = V_LONG; }
|
||||
| FLOAT { $$ = V_FLOAT; }
|
||||
| DOUBLE { $$ = V_DOUBLE; }
|
||||
| STRING_DECL { $$ = V_STRING; }
|
||||
| EVFLAG { $$ = V_EVFLAG; }
|
||||
;
|
||||
|
||||
sync_stmt /* sync <variable> <event flag> */
|
||||
: SYNC NAME subscript NAME SEMI_COLON { sync_stmt($2, $3, $4); }
|
||||
| SYNC NAME subscript TO NAME SEMI_COLON { sync_stmt($2, $3, $5); }
|
||||
: SYNC NAME TO NAME SEMI_COLON { sync_stmt($2, $4); }
|
||||
| SYNC NAME NAME SEMI_COLON { sync_stmt($2, $3); /* archaic syntax */ }
|
||||
;
|
||||
|
||||
program_body /* a program body is one or more state sets */
|
||||
: state_set
|
||||
| program_body state_set
|
||||
state_set_list /* a program body is one or more state sets */
|
||||
: state_set { $$ = $1; }
|
||||
| state_set_list state_set { $$ = link_expr($1, $2); }
|
||||
;
|
||||
|
||||
state_set /* define a state set */
|
||||
: STATE_SET NAME L_BRACKET state_set_body R_BRACKET { state_set($2); }
|
||||
| error { snc_err("state set", line_num, 3); }
|
||||
: STATE_SET NAME L_BRACKET state_list R_BRACKET
|
||||
{ $$ = expression(E_SS, $2, $4, 0); }
|
||||
| EXIT L_BRACKET stmt_list R_BRACKET
|
||||
{ exit_code($3); $$ = 0; }
|
||||
|
||||
| error { snc_err("state set"); }
|
||||
;
|
||||
|
||||
state_set_body /* define a state set body (one or more state blocks) */
|
||||
: state_block
|
||||
| state_set_body state_block
|
||||
| error { snc_err("state set body", line_num, 4); }
|
||||
state_list /* define a state set body (one or more states) */
|
||||
: state { $$ = $1; }
|
||||
| state_list state { $$ = link_expr($1, $2); }
|
||||
| error { snc_err("state set"); }
|
||||
;
|
||||
|
||||
state_block /* a block that defines a single state */
|
||||
: STATE NAME L_BRACKET trans_list R_BRACKET
|
||||
{ state_block($2); }
|
||||
| error { snc_err("state block", line_num, 11); }
|
||||
state /* a block that defines a single state */
|
||||
: STATE NAME L_BRACKET transition_list R_BRACKET
|
||||
{ $$ = expression(E_STATE, $2, $4, 0); }
|
||||
| error { snc_err("state block"); }
|
||||
;
|
||||
|
||||
trans_list /* all transitions for one state */
|
||||
: transition
|
||||
| trans_list transition
|
||||
| error { snc_err("transition", line_num, 5); }
|
||||
transition_list /* all transitions for one state */
|
||||
: transition { $$ = $1; }
|
||||
| transition_list transition { $$ = link_expr($1, $2); }
|
||||
| error { snc_err("transition"); }
|
||||
;
|
||||
|
||||
transition /* define a transition (e.g. "when (abc(x) | def(y, z)) state 2;" ) */
|
||||
: WHEN L_PAREN expression R_PAREN L_BRACKET action R_BRACKET STATE NAME
|
||||
{ transition($9, $3); }
|
||||
transition /* define a transition ("when" statment ) */
|
||||
: WHEN L_PAREN expr R_PAREN L_BRACKET stmt_list R_BRACKET STATE NAME
|
||||
{ $$ = expression(E_WHEN, $9, $3, $6); }
|
||||
;
|
||||
|
||||
expression /* general expression: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */
|
||||
/* Expr *expression(int type, char *value, Expr *left, Expr *right) */
|
||||
: NUMBER { $$ = expression(E_CONST, $1, (Expr *)0, (Expr *)0); }
|
||||
| STRING { $$ = expression(E_STRING, $1, (Expr *)0, (Expr *)0); }
|
||||
| NAME { $$ = expression(E_VAR, $1, (Expr *)0, (Expr *)0); }
|
||||
| function { $$ = $1; }
|
||||
| expression PLUS expression { $$ = expression(E_BINOP, "+", $1, $3); }
|
||||
| expression MINUS expression { $$ = expression(E_BINOP, "-", $1, $3); }
|
||||
| expression ASTERISK expression { $$ = expression(E_BINOP, "*", $1, $3); }
|
||||
| expression SLASH expression { $$ = expression(E_BINOP, "/", $1, $3); }
|
||||
| expression GT expression { $$ = expression(E_BINOP, ">", $1, $3); }
|
||||
| expression GE expression { $$ = expression(E_BINOP, ">=", $1, $3); }
|
||||
| expression EQ expression { $$ = expression(E_BINOP, "==", $1, $3); }
|
||||
| expression NE expression { $$ = expression(E_BINOP, "!=", $1, $3); }
|
||||
| expression LE expression { $$ = expression(E_BINOP, "<=", $1, $3); }
|
||||
| expression LT expression { $$ = expression(E_BINOP, "<", $1, $3); }
|
||||
| expression OR expression { $$ = expression(E_BINOP, "||", $1, $3); }
|
||||
| expression AND expression { $$ = expression(E_BINOP, "&&", $1, $3); }
|
||||
| expression EQUAL expression { $$ = expression(E_BINOP, "=", $1, $3); }
|
||||
| expression PLUS_EQUAL expression { $$ = expression(E_BINOP, "+=", $1, $3); }
|
||||
| expression MINUS_EQUAL expression { $$ = expression(E_BINOP, "-=", $1, $3); }
|
||||
| expression AND_EQUAL expression { $$ = expression(E_BINOP, "&=", $1, $3); }
|
||||
| expression OR_EQUAL expression { $$ = expression(E_BINOP, "|=", $1, $3); }
|
||||
| expression DIV_EQUAL expression { $$ = expression(E_BINOP, "/=", $1, $3); }
|
||||
| expression MULT_EQUAL expression { $$ = expression(E_BINOP, "*=", $1, $3); }
|
||||
| L_PAREN expression R_PAREN { $$ = expression(E_PAREN, "", (Expr *)0, $2); }
|
||||
| PLUS expression %prec UOP { $$ = expression(E_UNOP, "+", (Expr *)0, $2); }
|
||||
| MINUS expression %prec UOP { $$ = expression(E_UNOP, "-", (Expr *)0, $2); }
|
||||
| NOT expression { $$ = expression(E_UNOP, "!", (Expr *)0, $2); }
|
||||
| ASTERISK expression %prec UOP { $$ = expression(E_UNOP, "*", (Expr *)0, $2); }
|
||||
| AMPERSAND expression %prec UOP { $$ = expression(E_UNOP, "&", (Expr *)0, $2); }
|
||||
| expression L_SQ_BRACKET expression R_SQ_BRACKET %prec SUBSCRIPT
|
||||
expr /* general expr: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */
|
||||
/* Expr *expression(int type, char *value, Expr *left, Expr *right) */
|
||||
: expr binop expr { $$ = expression(E_BINOP, $2, $1, $3); }
|
||||
| expr asgnop expr { $$ = expression(E_ASGNOP, $2, $1, $3); }
|
||||
| unop expr %prec UOP { $$ = expression(E_UNOP, $1, $2, 0); }
|
||||
| NUMBER { $$ = expression(E_CONST, $1, 0, 0); }
|
||||
| STRING { $$ = expression(E_STRING, $1, 0, 0); }
|
||||
| NAME { $$ = expression(E_VAR, $1, 0, 0); }
|
||||
| NAME L_PAREN parameter R_PAREN { $$ = expression(E_FUNC, $1, $3, 0); }
|
||||
| EXIT L_PAREN parameter R_PAREN { $$ = expression(E_FUNC, "exit", $3, 0); }
|
||||
| L_PAREN expr R_PAREN { $$ = expression(E_PAREN, "", $2, 0); }
|
||||
| expr L_SQ_BRACKET expr R_SQ_BRACKET %prec SUBSCRIPT
|
||||
{ $$ = expression(E_SUBSCR, "", $1, $3); }
|
||||
| /* empty */ { $$ = expression(E_EMPTY, ""); }
|
||||
| /* empty */ { $$ = expression(E_EMPTY, "", 0, 0); }
|
||||
;
|
||||
|
||||
function /* function */
|
||||
: NAME L_PAREN parameter R_PAREN { $$ = expression(E_FUNC, $1, (Expr *)0, $3); }
|
||||
unop /* Unary operators */
|
||||
: PLUS { $$ = "+"; }
|
||||
| MINUS { $$ = "-"; }
|
||||
| ASTERISK { $$ = "*"; }
|
||||
| AMPERSAND { $$ = "&"; }
|
||||
| NOT { $$ = "!"; }
|
||||
;
|
||||
|
||||
binop /* Binary operators */
|
||||
: MINUS { $$ = "-"; }
|
||||
| PLUS { $$ = "+"; }
|
||||
| ASTERISK { $$ = "*"; }
|
||||
| SLASH { $$ = "/"; }
|
||||
| GT { $$ = ">"; }
|
||||
| GE { $$ = ">="; }
|
||||
| EQ { $$ = "=="; }
|
||||
| NE { $$ = "!="; }
|
||||
| LE { $$ = "<="; }
|
||||
| LT { $$ = "<"; }
|
||||
| OR { $$ = "||"; }
|
||||
| AND { $$ = "&&"; }
|
||||
| L_SHIFT { $$ = "<<"; }
|
||||
| R_SHIFT { $$ = ">>"; }
|
||||
| BIT_OR { $$ = "|"; }
|
||||
| BIT_AND { $$ = "&"; }
|
||||
| COMPLEMENT { $$ = "^"; }
|
||||
| MODULO { $$ = "%"; }
|
||||
;
|
||||
|
||||
asgnop /* Assignment operators */
|
||||
: EQUAL { $$ = "="; }
|
||||
| PLUS_EQUAL { $$ = "+="; }
|
||||
| MINUS_EQUAL { $$ = "-="; }
|
||||
| AND_EQUAL { $$ = "&="; }
|
||||
| OR_EQUAL { $$ = "|="; }
|
||||
| DIV_EQUAL { $$ = "/="; }
|
||||
| MULT_EQUAL { $$ = "*="; }
|
||||
| MODULO_EQUAL { $$ = "%="; }
|
||||
| LEFT_EQUAL { $$ = "<<="; }
|
||||
| RIGHT_EQUAL { $$ = ">>="; }
|
||||
| CMPL_EQUAL { $$ = "^="; }
|
||||
;
|
||||
|
||||
parameter /* expr, expr, .... */
|
||||
: expression { $$ = parameter($1, 0); }
|
||||
| parameter COMMA expression { $$ = parameter($3, $1); }
|
||||
| /* empty */ { $$ = 0; }
|
||||
: expr { $$ = $1; }
|
||||
| parameter COMMA expr { $$ = link_expr($1, $3); }
|
||||
| /* empty */ { $$ = 0; }
|
||||
;
|
||||
|
||||
action /* action block for a single state */
|
||||
: /* Empty */
|
||||
| action_item
|
||||
| action action_item
|
||||
| error { snc_err("action", line_num, 8); }
|
||||
compound_stmt /* compound statement e.g. { ...; ...; ...; } */
|
||||
: L_BRACKET stmt_list R_BRACKET { $$ = expression(E_CMPND, "",$2, 0); }
|
||||
| error { snc_err("action statements"); }
|
||||
;
|
||||
|
||||
action_item /* define an action */
|
||||
: expression SEMI_COLON { action_stmt($1); }
|
||||
| C_STMT { action_c_stmt($1); }
|
||||
| error { snc_err("action statement", line_num, 9); }
|
||||
stmt_list
|
||||
: statement { $$ = $1; }
|
||||
| stmt_list statement { $$ = link_expr($1, $2); }
|
||||
| /* empty */ { $$ = 0; }
|
||||
;
|
||||
|
||||
statement
|
||||
: compound_stmt { $$ = $1; }
|
||||
| expr SEMI_COLON { $$ = expression(E_STMT, "",$1, 0); }
|
||||
| if_stmt { $$ = $1; }
|
||||
| else_stmt { $$ = $1; }
|
||||
| while_stmt { $$ = $1; }
|
||||
| C_STMT { $$ = expression(E_TEXT, "", $1, 0); }
|
||||
| pp_code { $$ = 0; }
|
||||
| error { snc_err("action statement"); }
|
||||
;
|
||||
|
||||
if_stmt
|
||||
: IF L_PAREN expr R_PAREN statement { $$ = expression(E_IF, "", $3, $5); }
|
||||
;
|
||||
|
||||
else_stmt
|
||||
: ELSE statement { $$ = expression(E_ELSE, "", $2, 0); }
|
||||
;
|
||||
|
||||
while_stmt
|
||||
: WHILE L_PAREN expr R_PAREN statement { $$ = expression(E_WHILE, "", $3, $5); }
|
||||
;
|
||||
|
||||
pp_code /* pre-processor code (e.g. # 1 "test.st") */
|
||||
: PP_SYMBOL NUMBER STRING CR { pp_code($2, $3, ""); }
|
||||
| PP_SYMBOL NUMBER STRING NUMBER CR { pp_code($2, $3, $4); }
|
||||
;
|
||||
|
||||
global_c
|
||||
: C_STMT { global_c_stmt($1); }
|
||||
;
|
||||
%%
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)snc_lex.l 1.1 10/16/90
|
||||
$Id$
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
/* Lexical analyzer for State Notation Compiler (snc).
|
||||
@@ -18,80 +18,114 @@
|
||||
|
||||
#include "parse.h"
|
||||
#include "y.tab.h" /* output from yacc */
|
||||
#include "stdio.h"
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#define RETURN(param) { printf("return(param)\n"); return(param); }
|
||||
#define RETURN(param) { fprintf(stderr, "return(param)\n"); return(param); }
|
||||
#else
|
||||
#define RETURN(param) return(param);
|
||||
#endif
|
||||
#define STR_BFR_SIZE 30000
|
||||
|
||||
extern int line_num; /* input line number */
|
||||
char str_bfr[STR_BFR_SIZE]; /* holding place for strings */
|
||||
char *str_next = str_bfr; /* current ptr to str_bfr */
|
||||
char *c_str; /* Start of current string in str_bfr */
|
||||
int nc;
|
||||
double atof();
|
||||
int one_line_c_code;
|
||||
extern int line_num, c_line_num; /* input line number */
|
||||
extern int warn_flag; /* compiler warning flag */
|
||||
char str_bfr[STR_BFR_SIZE]; /* holding place for strings */
|
||||
char *str_next = str_bfr; /* current ptr to str_bfr */
|
||||
char *c_str; /* Start of current string in str_bfr */
|
||||
int nc;
|
||||
double atof();
|
||||
int one_line_c_code;
|
||||
|
||||
%}
|
||||
|
||||
/* Start conditions (SNL, C code, comment, and string) */
|
||||
%Start SNL C_CODE COMMENT STR
|
||||
/* Start conditions (SNL, C code, comment, string, pre-processor, pre-proc. string) */
|
||||
%Start SNL C_CODE COMMENT STR PP PP_STR
|
||||
|
||||
NAME [a-zA-Z][a-zA-Z0-9_]*
|
||||
FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
|
||||
%% /* Begin rules */
|
||||
<C_CODE>. *str_next++ = yytext[0];
|
||||
<C_CODE>\n {
|
||||
*str_next++ = '\n';
|
||||
line_num++;
|
||||
if (one_line_c_code)
|
||||
{
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
}
|
||||
<C_CODE>"}%" {
|
||||
<C_CODE>\n {
|
||||
*str_next++ = '\n';
|
||||
line_num++;
|
||||
if (one_line_c_code)
|
||||
{
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
}
|
||||
<C_CODE>"}%" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
<COMMENT>\n line_num++;
|
||||
<COMMENT>"*/" BEGIN SNL;
|
||||
<COMMENT>. ;
|
||||
<STR>"\\\"" {
|
||||
*str_next++ = yytext[0];
|
||||
*str_next++ = yytext[1];
|
||||
}
|
||||
<STR>\" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(STRING);
|
||||
}
|
||||
<STR>"\\\"" {
|
||||
*str_next++ = yytext[0];
|
||||
*str_next++ = yytext[1];
|
||||
}
|
||||
<STR>\" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(STRING);
|
||||
}
|
||||
<STR>. { *str_next++ = yytext[0]; }
|
||||
<STR>\n { *str_next++ = '?'; line_num++; }
|
||||
<STR>\n { *str_next++ = '?';
|
||||
if (warn_flag)
|
||||
fprintf(stderr, "Warning: newline in string, line %d\n",
|
||||
line_num);
|
||||
line_num++;
|
||||
}
|
||||
<PP>{FPNUM} { nc = strlen(yytext);
|
||||
bcopy(yytext, str_next, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<PP>\" { c_str = str_next; BEGIN PP_STR; }
|
||||
<PP>\n {
|
||||
BEGIN SNL;
|
||||
RETURN(CR);
|
||||
}
|
||||
<PP>[\t\ ]* /* no action */ ;
|
||||
<PP>. {
|
||||
}
|
||||
<PP_STR>\" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN PP;
|
||||
RETURN(STRING);
|
||||
}
|
||||
<PP_STR>. { *str_next++ = yytext[0]; }
|
||||
<PP_STR>\n { *str_next++ = '?'; line_num++; }
|
||||
<SNL>\n { line_num++; }
|
||||
<SNL>"%{" {
|
||||
c_str = str_next;
|
||||
one_line_c_code = FALSE;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>"%%" {
|
||||
c_str = str_next;
|
||||
one_line_c_code = TRUE;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>"%{" {
|
||||
c_str = str_next;
|
||||
one_line_c_code = FALSE;
|
||||
c_line_num = line_num;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>"%%" {
|
||||
c_str = str_next;
|
||||
one_line_c_code = TRUE;
|
||||
c_line_num = line_num;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>^# {
|
||||
BEGIN PP;
|
||||
RETURN(PP_SYMBOL);
|
||||
}
|
||||
<SNL>"/*" BEGIN COMMENT;
|
||||
<SNL>\" { c_str = str_next; BEGIN STR; }
|
||||
<SNL>"ss" RETURN(STATE_SET);
|
||||
@@ -99,46 +133,41 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
<SNL>"when" RETURN(WHEN);
|
||||
<SNL>"monitor" RETURN(MONITOR);
|
||||
<SNL>"assign" RETURN(ASSIGN);
|
||||
<SNL>"char" RETURN(CHAR);
|
||||
<SNL>"short" RETURN(SHORT);
|
||||
<SNL>"int" RETURN(INT);
|
||||
<SNL>"long" RETURN(LONG);
|
||||
<SNL>"float" RETURN(FLOAT);
|
||||
<SNL>"double" RETURN(DOUBLE);
|
||||
<SNL>"short" RETURN(SHORT);
|
||||
<SNL>"char" RETURN(CHAR);
|
||||
<SNL>"string" RETURN(STRING_DECL);
|
||||
<SNL>"to" RETURN(TO);
|
||||
<SNL>"define" RETURN(DEFINE);
|
||||
<SNL>"program" RETURN(PROGRAM);
|
||||
<SNL>"debug" RETURN(DEBUG_PRINT);
|
||||
<SNL>"evflag" RETURN(EVFLAG);
|
||||
<SNL>"sync" RETURN(SYNC);
|
||||
<SNL>"if" RETURN(IF);
|
||||
<SNL>"else" RETURN(ELSE);
|
||||
<SNL>"while" RETURN(WHILE);
|
||||
<SNL>"exit" RETURN(EXIT);
|
||||
<SNL>"TRUE" { yylval.pchar = "1";
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<SNL>"FALSE" {
|
||||
yylval.pchar = "0";
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<SNL>{NAME} {
|
||||
nc = strlen(yytext);
|
||||
bcopy(yytext, str_next, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
RETURN(NAME);
|
||||
}
|
||||
<SNL>\= RETURN(EQUAL);
|
||||
<SNL>\: RETURN(COLON);
|
||||
<SNL>\& RETURN(AMPERSAND);
|
||||
<SNL>\* RETURN(ASTERISK);
|
||||
<SNL>\{ RETURN(L_BRACKET);
|
||||
<SNL>\} RETURN(R_BRACKET);
|
||||
<SNL>\[ RETURN(L_SQ_BRACKET);
|
||||
<SNL>\] RETURN(R_SQ_BRACKET);
|
||||
<SNL>\; RETURN(SEMI_COLON);
|
||||
<SNL>\. RETURN(PERIOD);
|
||||
<SNL>\( RETURN(L_PAREN);
|
||||
<SNL>\) RETURN(R_PAREN);
|
||||
<SNL>\, RETURN(COMMA);
|
||||
<SNL>"|" RETURN(OR);
|
||||
<SNL>"&" RETURN(AND);
|
||||
}
|
||||
<SNL>"<<=" RETURN(LEFT_EQUAL);
|
||||
<SNL>">>=" RETURN(RIGHT_EQUAL);
|
||||
<SNL>"||" RETURN(OR);
|
||||
<SNL>"&&" RETURN(AND);
|
||||
<SNL>"+" RETURN(PLUS);
|
||||
<SNL>"-" RETURN(MINUS);
|
||||
<SNL>"/" RETURN(SLASH);
|
||||
<SNL>">" RETURN(GT);
|
||||
<SNL>">>" RETURN(R_SHIFT);
|
||||
<SNL>">=" RETURN(GE);
|
||||
<SNL>"==" RETURN(EQ);
|
||||
<SNL>"+=" RETURN(PLUS_EQUAL);
|
||||
@@ -148,17 +177,44 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
<SNL>"&=" RETURN(AND_EQUAL);
|
||||
<SNL>"|=" RETURN(OR_EQUAL);
|
||||
<SNL>"!=" RETURN(NE);
|
||||
<SNL>"<<" RETURN(L_SHIFT);
|
||||
<SNL>"<=" RETURN(LE);
|
||||
<SNL>"%=" RETURN(MODULO_EQUAL);
|
||||
<SNL>"^=" RETURN(CMPL_EQUAL);
|
||||
<SNL>"+" RETURN(PLUS);
|
||||
<SNL>"-" RETURN(MINUS);
|
||||
<SNL>"/" RETURN(SLASH);
|
||||
<SNL>"<" RETURN(LT);
|
||||
<SNL>"!" RETURN(NOT);
|
||||
<SNL>">" RETURN(GT);
|
||||
<SNL>"|" RETURN(BIT_OR);
|
||||
<SNL>"&" RETURN(BIT_AND);
|
||||
<SNL>"^" RETURN(COMPLEMENT);
|
||||
<SNL>"%" RETURN(MODULO);
|
||||
<SNL>"=" RETURN(EQUAL);
|
||||
<SNL>"&" RETURN(AMPERSAND);
|
||||
<SNL>"*" RETURN(ASTERISK);
|
||||
<SNL>"{" RETURN(L_BRACKET);
|
||||
<SNL>"}" RETURN(R_BRACKET);
|
||||
<SNL>"[" RETURN(L_SQ_BRACKET);
|
||||
<SNL>"]" RETURN(R_SQ_BRACKET);
|
||||
<SNL>":" RETURN(COLON);
|
||||
<SNL>";" RETURN(SEMI_COLON);
|
||||
<SNL>"." RETURN(PERIOD);
|
||||
<SNL>"(" RETURN(L_PAREN);
|
||||
<SNL>")" RETURN(R_PAREN);
|
||||
<SNL>"," RETURN(COMMA);
|
||||
<SNL>{FPNUM} {
|
||||
nc = strlen(yytext);
|
||||
bcopy(yytext, str_next, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<SNL>[\t\ ]* ;
|
||||
}
|
||||
<SNL>[\t\ ]* /* no action */ ;
|
||||
<SNL>. RETURN(BAD_CHAR);
|
||||
# { /* somehow "^#" doesn't work if it's first char */
|
||||
BEGIN PP;
|
||||
RETURN(PP_SYMBOL)
|
||||
}
|
||||
.|\n { line_num = 1; BEGIN SNL; yyless(0); }
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)snc_main.c 1.1 10/16/90
|
||||
@(#)snc_main.c 1.2 4/17/91
|
||||
DESCRIPTION: Main program and miscellaneous routines for
|
||||
State Notation Compiler.
|
||||
|
||||
@@ -13,10 +13,24 @@ extern char *sncVersion;
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/* SNC Globals: */
|
||||
int line_no = 1; /* input line number */
|
||||
char in_file[200]; /* input file name */
|
||||
char out_file[200]; /* output file name */
|
||||
char in_file[200]; /* input file name */
|
||||
char out_file[200]; /* output file name */
|
||||
char *src_file; /* ptr to (effective) source file name */
|
||||
int line_num; /* current src file line number */
|
||||
int c_line_num; /* line number for beginning of C code */
|
||||
/* Flags: */
|
||||
int async_flag = FALSE; /* do pvGet() asynchronously */
|
||||
int conn_flag = TRUE; /* wait for all connections to complete */
|
||||
int debug_flag = FALSE; /* run-time debug */
|
||||
int line_flag = TRUE; /* line numbering */
|
||||
int reent_flag = FALSE; /* reentrant at run-time */
|
||||
int warn_flag = TRUE; /* compiler warnings */
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: main
|
||||
@@ -44,11 +58,9 @@ char *argv[];
|
||||
FILE *infp, *outfp, *freopen();
|
||||
extern char in_file[], out_file[];
|
||||
|
||||
/* Use line buffered output */
|
||||
setlinebuf(stdout);
|
||||
|
||||
/* Get command arguments */
|
||||
get_args(argc, argv);
|
||||
|
||||
/* Redirect input stream from specified file */
|
||||
infp = freopen(in_file, "r", stdin);
|
||||
if (infp == NULL)
|
||||
@@ -67,8 +79,15 @@ char *argv[];
|
||||
exit(1);
|
||||
}
|
||||
#endif REDIRECT
|
||||
printf(
|
||||
"/* %s: %s */\n\n", sncVersion, in_file);
|
||||
|
||||
/* src_file is used to mark the output file for snc & cc errors */
|
||||
src_file = in_file;
|
||||
|
||||
/* Use line buffered output */
|
||||
setlinebuf(stdout);
|
||||
setlinebuf(stderr);
|
||||
|
||||
printf("/* %s: %s */\n\n", sncVersion, in_file);
|
||||
|
||||
/* Initialize parser */
|
||||
init_snc();
|
||||
@@ -96,17 +115,79 @@ get_args(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char in_file[], out_file[];
|
||||
int ls;
|
||||
char *s;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "%s\n", sncVersion);
|
||||
fprintf(stderr, "Usage: snc infile\n");
|
||||
fprintf(stderr, "Usage: snc +/-flags infile\n");
|
||||
fprintf(stderr, " +a - do async. pvGet\n");
|
||||
fprintf(stderr, " -c - don't wait for all connects\n");
|
||||
fprintf(stderr, " +d - turn on debug run-time option\n");
|
||||
fprintf(stderr, " -l - supress line numbering\n");
|
||||
fprintf(stderr, " +r - make reentrant at run-time\n");
|
||||
fprintf(stderr, " -w - supress compiler warnings\n");
|
||||
exit(1);
|
||||
}
|
||||
s = argv[1];
|
||||
|
||||
for (argc--, argv++; argc > 0; argc--, argv++)
|
||||
{
|
||||
s = *argv;
|
||||
if (*s == '+' || *s == '-')
|
||||
get_flag(s);
|
||||
else
|
||||
get_in_file(s);
|
||||
}
|
||||
}
|
||||
|
||||
get_flag(s)
|
||||
char *s;
|
||||
{
|
||||
int flag_val;
|
||||
extern int debug_flag, line_flag, reent_flag, warn_flag;
|
||||
|
||||
if (*s == '+')
|
||||
flag_val = TRUE;
|
||||
else
|
||||
flag_val = FALSE;
|
||||
|
||||
switch (s[1])
|
||||
{
|
||||
case 'a':
|
||||
async_flag = flag_val;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
conn_flag = flag_val;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
debug_flag = flag_val;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
line_flag = flag_val;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
reent_flag = flag_val;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
warn_flag = flag_val;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown flag: \"%s\"\n", s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
get_in_file(s)
|
||||
char *s;
|
||||
{
|
||||
extern char in_file[], out_file[];
|
||||
int ls;
|
||||
|
||||
ls = strlen(s);
|
||||
bcopy(s, in_file, ls);
|
||||
@@ -115,15 +196,18 @@ char *argv[];
|
||||
if ( strcmp(&in_file[ls-3], ".st") == 0 )
|
||||
{
|
||||
out_file[ls-2] = 'c';
|
||||
out_file[ls-1] = '\0';
|
||||
out_file[ls-1] = 0;
|
||||
}
|
||||
else if (in_file[ls-2] == '.')
|
||||
{ /* change suffix to 'c' */
|
||||
out_file[ls -1] = 'c';
|
||||
}
|
||||
else
|
||||
{
|
||||
{ /* append ".c" */
|
||||
out_file[ls] = '.';
|
||||
out_file[ls+1] = 'c';
|
||||
ls += 2;
|
||||
out_file[ls+2] = 0;
|
||||
}
|
||||
out_file[ls] = 0;
|
||||
return;
|
||||
}
|
||||
/*+************************************************************************
|
||||
@@ -142,13 +226,11 @@ char *argv[];
|
||||
*
|
||||
* NOTES:
|
||||
*-*************************************************************************/
|
||||
snc_err(err_txt, line, code)
|
||||
snc_err(err_txt)
|
||||
char *err_txt;
|
||||
int line, code;
|
||||
{
|
||||
fprintf(stderr, "Syntax error %d (%s) at line %d\n",
|
||||
code, err_txt, line);
|
||||
exit(code);
|
||||
fprintf(stderr, " %s\n", err_txt);
|
||||
exit(1);
|
||||
}
|
||||
/*+************************************************************************
|
||||
* NAME: yyerror
|
||||
@@ -167,7 +249,10 @@ int line, code;
|
||||
yyerror(err)
|
||||
char *err;
|
||||
{
|
||||
fprintf(stderr, "%s: line no. %d\n", err, line_no);
|
||||
extern char *src_file;
|
||||
extern int line_num;
|
||||
|
||||
fprintf(stderr, "%s: line no. %d (%s)\n", err, line_num, src_file);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -178,6 +263,7 @@ char *err;
|
||||
* type argument I/O description
|
||||
* ---------------------------------------------------
|
||||
* int line_num I current line number
|
||||
* char src_file I effective source file
|
||||
*
|
||||
* RETURNS: n/a
|
||||
*
|
||||
@@ -186,9 +272,13 @@ char *err;
|
||||
*
|
||||
* NOTES:
|
||||
*-*************************************************************************/
|
||||
print_line_num(line_num)
|
||||
int line_num;
|
||||
print_line_num(line_num, src_file)
|
||||
int line_num;
|
||||
char *src_file;
|
||||
{
|
||||
printf("# line %d \"%s\"\n", line_num, in_file);
|
||||
extern int line_flag;
|
||||
|
||||
if (line_flag)
|
||||
printf("# line %d \"%s\"\n", line_num, src_file);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user