From 1f980e64f5e9c416220e70dad80d1d536de2ca42 Mon Sep 17 00:00:00 2001 From: Bob Zieman Date: Fri, 7 Jun 1991 18:31:41 +0000 Subject: [PATCH] installed latest gtac version of sequencer --- src/sequencer/Version | 2 +- src/sequencer/gen_ss_code.c | 465 ++++++++++++++++----------- src/sequencer/gen_tables.c | 2 +- src/sequencer/parse.c | 459 ++++++++------------------- src/sequencer/parse.h | 129 +++----- src/sequencer/phase2.c | 614 ++++++++++++++++++------------------ src/sequencer/seq_ca.c | 390 +++++++++++++++++------ src/sequencer/seq_mac.c | 63 ++-- src/sequencer/seq_main.c | 574 +++++++++++++++++---------------- src/sequencer/seq_qry.c | 155 ++++++--- src/sequencer/seq_task.c | 237 +++++++++----- src/sequencer/snc.y | 253 +++++++++------ src/sequencer/snc_lex.l | 198 +++++++----- src/sequencer/snc_main.c | 142 +++++++-- 14 files changed, 2048 insertions(+), 1635 deletions(-) diff --git a/src/sequencer/Version b/src/sequencer/Version index 9edc58bb1..661e7aead 100755 --- a/src/sequencer/Version +++ b/src/sequencer/Version @@ -1 +1 @@ -1.6.4 +1.7.3 diff --git a/src/sequencer/gen_ss_code.c b/src/sequencer/gen_ss_code.c index eea07ef6b..252906acc 100644 --- a/src/sequencer/gen_ss_code.c +++ b/src/sequencer/gen_ss_code.c @@ -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 #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"); +} diff --git a/src/sequencer/gen_tables.c b/src/sequencer/gen_tables.c index c76deb9f1..891d29c99 100644 --- a/src/sequencer/gen_tables.c +++ b/src/sequencer/gen_tables.c @@ -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 diff --git a/src/sequencer/parse.c b/src/sequencer/parse.c index 0f383d76e..3546f3ea2 100644 --- a/src/sequencer/parse.c +++ b/src/sequencer/parse.c @@ -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 diff --git a/src/sequencer/parse.h b/src/sequencer/parse.h index 6ffc8c98e..b7c9bc448 100644 --- a/src/sequencer/parse.h +++ b/src/sequencer/parse.h @@ -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 */ diff --git a/src/sequencer/phase2.c b/src/sequencer/phase2.c index c64c9d80a..164234819 100644 --- a/src/sequencer/phase2.c +++ b/src/sequencer/phase2.c @@ -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 #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); + } +} + diff --git a/src/sequencer/seq_ca.c b/src/sequencer/seq_ca.c index 868ff3e13..c55c26246 100644 --- a/src/sequencer/seq_ca.c +++ b/src/sequencer/seq_ca.c @@ -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; +} diff --git a/src/sequencer/seq_mac.c b/src/sequencer/seq_mac.c index daf4a84d0..372d3263c 100644 --- a/src/sequencer/seq_mac.c +++ b/src/sequencer/seq_mac.c @@ -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++) { diff --git a/src/sequencer/seq_main.c b/src/sequencer/seq_main.c index d0922affa..6c3e80c40 100644 --- a/src/sequencer/seq_main.c +++ b/src/sequencer/seq_main.c @@ -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; +} diff --git a/src/sequencer/seq_qry.c b/src/sequencer/seq_qry.c index b4a1c36ef..43898aa96 100644 --- a/src/sequencer/seq_qry.c +++ b/src/sequencer/seq_qry.c @@ -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 \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 \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() { diff --git a/src/sequencer/seq_task.c b/src/sequencer/seq_task.c index 739568e0b..6f39ae4eb 100644 --- a/src/sequencer/seq_task.c +++ b/src/sequencer/seq_task.c @@ -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; } diff --git a/src/sequencer/snc.y b/src/sequencer/snc.y index b86d5525a..3bb4ddab0 100644 --- a/src/sequencer/snc.y +++ b/src/sequencer/snc.y @@ -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 #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 STATE STATE_SET -%token NUMBER NAME DBNAME +%token NUMBER NAME %token 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 STRING %token C_STMT +%token IF ELSE WHILE +%token PP_SYMBOL CR %type type -%type subscript -%type parameter function expression -/* precidence rules for expression evaluation */ +%type subscript binop asgnop unop +%type state_set_list state_set state_list state transition_list transition +%type parameter expr +%type 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 [,] to ;' */ - /* 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 to ;' */ +: 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 */ -: 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); } +; %% + diff --git a/src/sequencer/snc_lex.l b/src/sequencer/snc_lex.l index 80d9f0785..704f23c49 100644 --- a/src/sequencer/snc_lex.l +++ b/src/sequencer/snc_lex.l @@ -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 */ . *str_next++ = yytext[0]; -\n { - *str_next++ = '\n'; - line_num++; - if (one_line_c_code) - { - *str_next++ = 0; - yylval.pchar = c_str; - BEGIN SNL; - RETURN(C_STMT); - } - } -"}%" { +\n { + *str_next++ = '\n'; + line_num++; + if (one_line_c_code) + { *str_next++ = 0; yylval.pchar = c_str; BEGIN SNL; RETURN(C_STMT); } +} +"}%" { + *str_next++ = 0; + yylval.pchar = c_str; + BEGIN SNL; + RETURN(C_STMT); +} \n line_num++; "*/" BEGIN SNL; . ; -"\\\"" { - *str_next++ = yytext[0]; - *str_next++ = yytext[1]; - } -\" { - *str_next++ = 0; - yylval.pchar = c_str; - BEGIN SNL; - RETURN(STRING); - } +"\\\"" { + *str_next++ = yytext[0]; + *str_next++ = yytext[1]; +} +\" { + *str_next++ = 0; + yylval.pchar = c_str; + BEGIN SNL; + RETURN(STRING); +} . { *str_next++ = yytext[0]; } -\n { *str_next++ = '?'; line_num++; } +\n { *str_next++ = '?'; + if (warn_flag) + fprintf(stderr, "Warning: newline in string, line %d\n", + line_num); + line_num++; +} +{FPNUM} { nc = strlen(yytext); + bcopy(yytext, str_next, nc+1); + yylval.pchar = str_next; + str_next += nc+1; + RETURN(NUMBER); +} +\" { c_str = str_next; BEGIN PP_STR; } +\n { + BEGIN SNL; + RETURN(CR); +} +[\t\ ]* /* no action */ ; +. { +} +\" { + *str_next++ = 0; + yylval.pchar = c_str; + BEGIN PP; + RETURN(STRING); +} +. { *str_next++ = yytext[0]; } +\n { *str_next++ = '?'; line_num++; } \n { line_num++; } -"%{" { - c_str = str_next; - one_line_c_code = FALSE; - BEGIN C_CODE; - } -"%%" { - c_str = str_next; - one_line_c_code = TRUE; - BEGIN C_CODE; - } +"%{" { + c_str = str_next; + one_line_c_code = FALSE; + c_line_num = line_num; + BEGIN C_CODE; +} +"%%" { + c_str = str_next; + one_line_c_code = TRUE; + c_line_num = line_num; + BEGIN C_CODE; +} +^# { + BEGIN PP; + RETURN(PP_SYMBOL); +} "/*" BEGIN COMMENT; \" { c_str = str_next; BEGIN STR; } "ss" RETURN(STATE_SET); @@ -99,46 +133,41 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+)) "when" RETURN(WHEN); "monitor" RETURN(MONITOR); "assign" RETURN(ASSIGN); +"char" RETURN(CHAR); +"short" RETURN(SHORT); "int" RETURN(INT); +"long" RETURN(LONG); "float" RETURN(FLOAT); "double" RETURN(DOUBLE); -"short" RETURN(SHORT); -"char" RETURN(CHAR); "string" RETURN(STRING_DECL); "to" RETURN(TO); -"define" RETURN(DEFINE); "program" RETURN(PROGRAM); "debug" RETURN(DEBUG_PRINT); "evflag" RETURN(EVFLAG); "sync" RETURN(SYNC); +"if" RETURN(IF); +"else" RETURN(ELSE); +"while" RETURN(WHILE); +"exit" RETURN(EXIT); +"TRUE" { yylval.pchar = "1"; + RETURN(NUMBER); +} +"FALSE" { + yylval.pchar = "0"; + RETURN(NUMBER); +} {NAME} { nc = strlen(yytext); bcopy(yytext, str_next, nc+1); yylval.pchar = str_next; str_next += nc+1; RETURN(NAME); - } -\= RETURN(EQUAL); -\: RETURN(COLON); -\& RETURN(AMPERSAND); -\* RETURN(ASTERISK); -\{ RETURN(L_BRACKET); -\} RETURN(R_BRACKET); -\[ RETURN(L_SQ_BRACKET); -\] RETURN(R_SQ_BRACKET); -\; RETURN(SEMI_COLON); -\. RETURN(PERIOD); -\( RETURN(L_PAREN); -\) RETURN(R_PAREN); -\, RETURN(COMMA); -"|" RETURN(OR); -"&" RETURN(AND); +} +"<<=" RETURN(LEFT_EQUAL); +">>=" RETURN(RIGHT_EQUAL); "||" RETURN(OR); "&&" RETURN(AND); -"+" RETURN(PLUS); -"-" RETURN(MINUS); -"/" RETURN(SLASH); -">" RETURN(GT); +">>" RETURN(R_SHIFT); ">=" RETURN(GE); "==" RETURN(EQ); "+=" RETURN(PLUS_EQUAL); @@ -148,17 +177,44 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+)) "&=" RETURN(AND_EQUAL); "|=" RETURN(OR_EQUAL); "!=" RETURN(NE); +"<<" RETURN(L_SHIFT); "<=" RETURN(LE); +"%=" RETURN(MODULO_EQUAL); +"^=" RETURN(CMPL_EQUAL); +"+" RETURN(PLUS); +"-" RETURN(MINUS); +"/" RETURN(SLASH); "<" RETURN(LT); -"!" RETURN(NOT); +">" RETURN(GT); +"|" RETURN(BIT_OR); +"&" RETURN(BIT_AND); +"^" RETURN(COMPLEMENT); +"%" RETURN(MODULO); +"=" RETURN(EQUAL); +"&" RETURN(AMPERSAND); +"*" RETURN(ASTERISK); +"{" RETURN(L_BRACKET); +"}" RETURN(R_BRACKET); +"[" RETURN(L_SQ_BRACKET); +"]" RETURN(R_SQ_BRACKET); +":" RETURN(COLON); +";" RETURN(SEMI_COLON); +"." RETURN(PERIOD); +"(" RETURN(L_PAREN); +")" RETURN(R_PAREN); +"," RETURN(COMMA); {FPNUM} { nc = strlen(yytext); bcopy(yytext, str_next, nc+1); yylval.pchar = str_next; str_next += nc+1; RETURN(NUMBER); - } -[\t\ ]* ; +} +[\t\ ]* /* no action */ ; . 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); } diff --git a/src/sequencer/snc_main.c b/src/sequencer/snc_main.c index e69173128..289319a46 100644 --- a/src/sequencer/snc_main.c +++ b/src/sequencer/snc_main.c @@ -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 +#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; }