Initial revision
This commit is contained in:
4
src/sequencer/README
Normal file
4
src/sequencer/README
Normal file
@@ -0,0 +1,4 @@
|
||||
###
|
||||
### 3 Apr. 1991 (MDA) moved seq.c to seq_main.c for consistency with
|
||||
### snc, and for ease of use in Imakefiles...
|
||||
###
|
||||
1
src/sequencer/Version
Executable file
1
src/sequencer/Version
Executable file
@@ -0,0 +1 @@
|
||||
1.6.4
|
||||
400
src/sequencer/gen_ss_code.c
Normal file
400
src/sequencer/gen_ss_code.c
Normal file
@@ -0,0 +1,400 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)gen_ss_code.c 1.3 1/16/91
|
||||
DESCRIPTION: gen_ss_code.c -- routines to generate state set code
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include "seq.h"
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: gen_ss_code
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* ---------------------------------------------------
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* FUNCTION: Generate state set C code from tables.
|
||||
*
|
||||
* NOTES: All inputs are external globals.
|
||||
*-*************************************************************************/
|
||||
|
||||
#define EVENT_STMT 1
|
||||
#define ACTION_STMT 2
|
||||
#define DELAY_STMT 3
|
||||
|
||||
gen_ss_code()
|
||||
{
|
||||
extern LIST ss_list;
|
||||
StateSet *ssp;
|
||||
State *sp;
|
||||
|
||||
/* For each state set ... */
|
||||
for (ssp = firstSS(&ss_list); ssp != NULL; ssp = nextSS(ssp))
|
||||
{
|
||||
/* For each state ... */
|
||||
for (sp = firstState(&ssp->S_list); sp != NULL; sp = nextState(sp))
|
||||
{
|
||||
/* Generate delay processing function */
|
||||
gen_delay_func(sp, ssp);
|
||||
|
||||
/* Generate event processing function */
|
||||
gen_event_func(sp, ssp);
|
||||
|
||||
/* Generate action processing function */
|
||||
gen_action_func(sp, ssp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Generate action processing functions:
|
||||
Each state has one action routine. It's name is derived from the
|
||||
state set name and the state name.
|
||||
*/
|
||||
gen_action_func(sp, ssp)
|
||||
State *sp;
|
||||
StateSet *ssp; /* Parent state set */
|
||||
{
|
||||
Trans *tp;
|
||||
Action *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);
|
||||
/* 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("\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))
|
||||
{
|
||||
/* "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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* end of case */
|
||||
printf("\t\treturn;\n");
|
||||
trans_num++;
|
||||
}
|
||||
/* end of switch stmt */
|
||||
printf("\t}\n");
|
||||
/* end of function */
|
||||
printf("}\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate a C function that checks events for a particular state */
|
||||
gen_event_func(sp, ssp)
|
||||
State *sp;
|
||||
StateSet *ssp;
|
||||
{
|
||||
Trans *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);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_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))
|
||||
{
|
||||
print_line_num(tp->line_num);
|
||||
printf("\tif (");
|
||||
eval_expr(EVENT_STMT, tp->event_expr, sp);
|
||||
/* 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);
|
||||
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);
|
||||
index = 0; /* default to 1-st state */
|
||||
printf("\t\t/* state %s does not exist */\n",
|
||||
tp->new_state_name);
|
||||
}
|
||||
printf("\t\tss_ptr->next_state = ss_ptr->states + %d;\n", index);
|
||||
printf("\t\tss_ptr->trans_num = %d;\n", trans_num);
|
||||
printf("\t\treturn TRUE;\n\t}\n");
|
||||
trans_num++;
|
||||
}
|
||||
printf("\treturn FALSE;\n");
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
/* Generate delay processing function for a state */
|
||||
gen_delay_func(sp, ssp)
|
||||
State *sp;
|
||||
StateSet *ssp;
|
||||
{
|
||||
Trans *tp;
|
||||
|
||||
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))
|
||||
{
|
||||
print_line_num(tp->line_num);
|
||||
eval_delay(tp->event_expr, sp);
|
||||
}
|
||||
printf("}\n");
|
||||
if (sp->ndelay > ssp->ndelay)
|
||||
ssp->ndelay = sp->ndelay; /* max # delay calls in ss */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* 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 */
|
||||
{
|
||||
Expr *epf;
|
||||
int nparams;
|
||||
|
||||
switch(ep->type)
|
||||
{
|
||||
case E_VAR:
|
||||
printf("%s", ep->value.var->name);
|
||||
break;
|
||||
case E_CONST:
|
||||
printf("%s", ep->value.const);
|
||||
break;
|
||||
case E_STRING:
|
||||
printf("\"%s\"", ep->value.const);
|
||||
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;
|
||||
epf = epf->next, nparams++)
|
||||
{
|
||||
if (nparams > 0)
|
||||
printf(" ,");
|
||||
eval_expr(stmt_type, epf, sp);
|
||||
}
|
||||
printf(") ");
|
||||
break;
|
||||
case E_BINOP:
|
||||
eval_expr(stmt_type, ep->left, sp);
|
||||
printf("%s", ep->value.const);
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
break;
|
||||
case E_PAREN:
|
||||
printf("(");
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
printf(")");
|
||||
break;
|
||||
case E_UNOP:
|
||||
printf("%s", ep->value.const);
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
break;
|
||||
case E_SUBSCR:
|
||||
eval_expr(stmt_type, ep->left, sp);
|
||||
printf("[");
|
||||
eval_expr(stmt_type, ep->right, sp);
|
||||
printf("]");
|
||||
break;
|
||||
default:
|
||||
if (stmt_type == EVENT_STMT)
|
||||
printf("TRUE"); /* empty event statement defaults to TRUE */
|
||||
else
|
||||
printf(" ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
enum fcode { F_NONE, F_EFSET, F_EFTEST, F_PVGET, F_PVPUT, F_DELAY };
|
||||
|
||||
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;
|
||||
return F_NONE;
|
||||
}
|
||||
|
||||
/* Process special function (returns TRUE if this is a special function) */
|
||||
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 */
|
||||
{
|
||||
char *fname; /* function name */
|
||||
Expr *ep1; /* 1-st parameter */
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
enum fcode func_code;
|
||||
|
||||
fname = ep->value.const;
|
||||
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 */
|
||||
if ( (ep1 != 0) && (ep1->type == E_VAR) )
|
||||
{
|
||||
vp = ep1->value.var;
|
||||
cp = vp->chan;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp = 0;
|
||||
cp = 0;
|
||||
}
|
||||
|
||||
if (func_code == F_EFSET || func_code == 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");
|
||||
}
|
||||
else if (func_code == F_EFSET && stmt_type == EVENT_STMT)
|
||||
{
|
||||
fprintf(stderr, "Line %d: ", ep->line_num);
|
||||
fprintf(stderr,
|
||||
"efSet() cannot be used as an event.\n");
|
||||
}
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
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++);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
10
src/sequencer/makeSeqVersion
Executable file
10
src/sequencer/makeSeqVersion
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/csh -f
|
||||
#
|
||||
# makeSeqVersion - create the sequencer version module
|
||||
#
|
||||
set VERSION = `cat Version`
|
||||
set DATE = `date`
|
||||
echo '/* seqVersion.c - version & date */'
|
||||
echo '/* Created by makeVersion */'
|
||||
echo 'char *seqVersion = "@(#)SEQ Version '${VERSION}': '${DATE}'";'
|
||||
|
||||
10
src/sequencer/makeVersion
Executable file
10
src/sequencer/makeVersion
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/csh -f
|
||||
#
|
||||
# makeVersion - create the snc version module
|
||||
#
|
||||
set VERSION = `cat Version`
|
||||
set DATE = `date`
|
||||
echo '/* sncVersion.c - version & date */'
|
||||
echo '/* Created by makeVersion */'
|
||||
echo 'char *sncVersion = "@(#)SNC Version '${VERSION}': '${DATE}'";'
|
||||
|
||||
594
src/sequencer/parse.c
Normal file
594
src/sequencer/parse.c
Normal file
@@ -0,0 +1,594 @@
|
||||
/* #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
|
||||
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.
|
||||
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
|
||||
/*====================== Includes, globals, & defines ====================*/
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include "parse.h" /* defines linked list structures */
|
||||
#include <math.h>
|
||||
#include "db_access.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif TRUE
|
||||
|
||||
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 */
|
||||
|
||||
LIST ss_list; /* start of state-set 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 */
|
||||
/*+************************************************************************
|
||||
* NAME: snc_init
|
||||
*
|
||||
* CALLING SEQUENCE: none
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* FUNCTION: Initialize state program tables & linked lists
|
||||
*
|
||||
* NOTES:
|
||||
*-*************************************************************************/
|
||||
init_snc()
|
||||
{
|
||||
lstInit(&defn_c_list);
|
||||
lstInit(&ss_list);
|
||||
lstInit(&var_list);
|
||||
lstInit(&chan_list);
|
||||
lstInit(&state_list);
|
||||
lstInit(&action_list);
|
||||
lstInit(&trans_list);
|
||||
return;
|
||||
}
|
||||
/*+************************************************************************
|
||||
* NAME: program_name
|
||||
*
|
||||
* CALLING SEQUENCE: none
|
||||
* type argument I/O description
|
||||
* -----------------------------------------------------------------
|
||||
* char *pname I ptr to program name string
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* FUNCTION: Save program name for global use.
|
||||
*
|
||||
*-*************************************************************************/
|
||||
program_name(pname, pparam)
|
||||
char *pname, *pparam;
|
||||
{
|
||||
extern char *prog_name, *prog_param;
|
||||
|
||||
prog_name = pname;
|
||||
prog_param = pparam;
|
||||
#ifdef DEBUG
|
||||
printf("program name = %s\n", prog_name);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parsing a declaration statement */
|
||||
decl_stmt(type, name, s_length, value)
|
||||
int type; /* variable type (e.g. V_FLOAT) */
|
||||
char *name; /* ptr to variable name */
|
||||
char *s_length; /* array lth (NULL=single element) */
|
||||
char *value; /* initial value or NULL */
|
||||
{
|
||||
Var *vp;
|
||||
int length;
|
||||
|
||||
if (s_length == 0)
|
||||
length = 0;
|
||||
else if (type == V_STRING)
|
||||
length = MAX_STRING_SIZE;
|
||||
else
|
||||
{
|
||||
length = atoi(s_length);
|
||||
if (length < 0)
|
||||
length = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("variable decl: type=%d, name=%s, length=%d\n", type, name, length);
|
||||
#endif
|
||||
/* See if variable already declared */
|
||||
vp = (Var *)find_var(name);
|
||||
if (vp != 0)
|
||||
{
|
||||
fprintf(stderr, "variable %s already declared, line %d\n",
|
||||
name, line_num);
|
||||
return;
|
||||
}
|
||||
/* Build a struct for this variable */
|
||||
vp = allocVar();
|
||||
lstAdd(&var_list, (NODE *)vp);
|
||||
vp->name = name;
|
||||
vp->type = type;
|
||||
vp->length = length;
|
||||
vp->value = value; /* initial value or NULL */
|
||||
return;
|
||||
}
|
||||
|
||||
/* "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)
|
||||
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;
|
||||
|
||||
/* Find the variable */
|
||||
vp = (Var *)find_var(name);
|
||||
if (vp == 0)
|
||||
{
|
||||
fprintf(stderr, "assign: variable %s not declared, line %d\n",
|
||||
name, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build structure for this channel */
|
||||
cp = allocChan();
|
||||
lstAdd(&chan_list, (NODE *)cp);
|
||||
cp->var = vp; /* make connection to variable */
|
||||
vp->chan = cp; /* reverse ptr */
|
||||
cp->db_name = db_name; /* DB name */
|
||||
|
||||
/* 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)
|
||||
char *name; /* variable name (should be assigned) */
|
||||
char *offset; /* array offset */
|
||||
char *delta; /* monitor delta */
|
||||
{
|
||||
Chan *cp;
|
||||
int offs;
|
||||
|
||||
/* 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);
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "monitor: variable %s[%s] not assigned, line %d\n",
|
||||
name, offset, line_num);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enter monitor parameters */
|
||||
cp->mon_flag = TRUE;
|
||||
cp->delta = atof(delta);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parsing "sync" statement */
|
||||
sync_stmt(name, offset, ef_name)
|
||||
char *name;
|
||||
char *offset;
|
||||
char *ef_name;
|
||||
{
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
int offs;
|
||||
|
||||
/* Find the variable */
|
||||
if (offset == 0)
|
||||
offs = 0;
|
||||
else
|
||||
offs = atoi(offset);
|
||||
if (offs < 0)
|
||||
offs = 0;
|
||||
cp = (Chan *)find_chan(name, offs);
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "sync: variable %s[%s] not assigned, line %d\n",
|
||||
name, offset, line_num);
|
||||
return;
|
||||
}
|
||||
/* Find the event flag varible */
|
||||
vp = (Var *)find_var(ef_name);
|
||||
if (vp == 0 || vp->type != V_EVFLAG)
|
||||
{
|
||||
fprintf(stderr, "sync: e-f variable %s not declared, line %d\n",
|
||||
ef_name, line_num);
|
||||
return;
|
||||
}
|
||||
cp->ef_var = vp;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Definition C code */
|
||||
defn_c_stmt(c_str)
|
||||
char *c_str;
|
||||
{
|
||||
Action *ap;
|
||||
#ifdef DEBUG
|
||||
printf("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;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parsing "ss" statement */
|
||||
state_set(ss_name)
|
||||
char *ss_name;
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
char *name;
|
||||
{
|
||||
Var *vp;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("find_var, name=%s: ", name);
|
||||
#endif
|
||||
vp = firstVar(&var_list);
|
||||
while (vp != NULL)
|
||||
{
|
||||
if (strcmp(vp->name, name) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("found\n");
|
||||
#endif
|
||||
return (int)vp;
|
||||
}
|
||||
vp = nextVar(vp);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("not found\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find channel with same variable name and same offset */
|
||||
find_chan(name, offset)
|
||||
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)
|
||||
{
|
||||
return (int)cp;
|
||||
}
|
||||
}
|
||||
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;
|
||||
{
|
||||
debug_print_flag = atoi(flag);
|
||||
}
|
||||
|
||||
/* Parsing "program" statement */
|
||||
program(c_code)
|
||||
char *c_code;
|
||||
{
|
||||
global_c_code = c_code;
|
||||
phase2();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Build an expression list (hierarchical) */
|
||||
Expr *expression(type, value, left, right)
|
||||
int type;
|
||||
char *value;
|
||||
Expr *left, *right;
|
||||
{
|
||||
Expr *ep;
|
||||
|
||||
/* alloc a block for this item or expression */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "expression: type=%d, value=%s, left=%d, right=%d\n",
|
||||
type, value, left, right);
|
||||
#endif
|
||||
ep = allocExpr();
|
||||
ep->type = type;
|
||||
ep->value.const = 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;
|
||||
}
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
/* Check for defined constant */
|
||||
pre_defined_const(ep)
|
||||
Expr *ep;
|
||||
{
|
||||
if ( (strcmp(ep->value.const, "TRUE") == 0)
|
||||
|| (strcmp(ep->value.const, "FALSE") == 0) )
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Add a parameter (expression) to end of list */
|
||||
Expr *parameter(ep, p_list)
|
||||
Expr *ep;
|
||||
Expr *p_list; /* current list */
|
||||
{
|
||||
Expr *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;
|
||||
}
|
||||
|
||||
/*#define PHASE2*/
|
||||
#ifdef PHASE2
|
||||
phase2()
|
||||
{
|
||||
fprintf(stderr, "phase2() - dummy\07\n");
|
||||
}
|
||||
#endif PHASE2
|
||||
148
src/sequencer/parse.h
Normal file
148
src/sequencer/parse.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1989, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)parse.h 1.1 10/16/90
|
||||
DESCRIPTION: Structures for parsing the state notation language.
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
/* Data for these blocks are generated by the parsing routines for each
|
||||
** state set. The tables are then used to generate the run-time C code
|
||||
** for the sequencer. This decouples the parsing implementation from
|
||||
** the run-time code implementation.
|
||||
*/
|
||||
|
||||
#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 *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 line_num; /* line number */
|
||||
};
|
||||
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 */
|
||||
char *name; /* variable name */
|
||||
char *value; /* initial value or NULL */
|
||||
int type; /* var type */
|
||||
int length; /* array lth (0 if not an array) */
|
||||
int ef_num; /* event flag bit number */
|
||||
struct db_chan *chan; /* ptr to db channel struct or NULL */
|
||||
};
|
||||
typedef struct var Var;
|
||||
|
||||
struct db_chan /* DB channel */
|
||||
{
|
||||
NODE D_link; /* next db chan in list */
|
||||
char *db_name; /* db name if assigned */
|
||||
int index; /* channel array index */
|
||||
Var *var; /* ptr to variable definition */
|
||||
int offset; /* array offset (normally 0) */
|
||||
int length; /* sub-array length */
|
||||
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 */
|
||||
};
|
||||
typedef struct db_chan Chan;
|
||||
|
||||
/* 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 firstVar(head) (Var *)lstFirst( (LIST *)head )
|
||||
#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) */
|
||||
|
||||
/* Expression type */
|
||||
#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_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();*/
|
||||
475
src/sequencer/phase2.c
Normal file
475
src/sequencer/phase2.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)phase2.c 1.4 1/16/91
|
||||
DESCRIPTION: Phase 2 code generation routines for SNC.
|
||||
Produces code and tables in C output file.
|
||||
See also: gen_ss_code.c
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include "seq.h"
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: phase2
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* ---------------------------------------------------
|
||||
*
|
||||
* RETURNS: n/a
|
||||
*
|
||||
* FUNCTION: Generate C code from tables.
|
||||
*
|
||||
* 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 */
|
||||
|
||||
/* Count number of variables, db channels, and state sets defined */
|
||||
num_vars = lstCount((NODE *)&var_list);
|
||||
num_channels = db_chan_count();
|
||||
num_ss = lstCount((NODE *)&ss_list);
|
||||
|
||||
/* Generate preamble code */
|
||||
gen_preamble();
|
||||
|
||||
/* Generate variable declarations */
|
||||
gen_var_decl();
|
||||
|
||||
/* Generate definition C code */
|
||||
gen_defn_c_code();
|
||||
|
||||
/* Assign bits for event flags */
|
||||
assign_ef_bits();
|
||||
|
||||
/* Generate DB blocks */
|
||||
gen_db_blocks();
|
||||
|
||||
/* 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();
|
||||
|
||||
/* Output global C code */
|
||||
printf("%s\n", global_c_code);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Generate preamble (includes, defines, etc.) */
|
||||
gen_preamble()
|
||||
{
|
||||
printf("/* Program \"%s\" */\n", prog_name);
|
||||
|
||||
/* Include files */
|
||||
printf("#include \"seq.h\"\n");
|
||||
|
||||
/* 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 */
|
||||
printf("\nextern SPROG %s;\n", prog_name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
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);
|
||||
for (nv=0, vp = firstVar(&var_list); vp != NULL; nv++, vp = nextVar(vp))
|
||||
{
|
||||
switch (vp->type)
|
||||
{
|
||||
case V_CHAR:
|
||||
vstr = "char";
|
||||
break;
|
||||
case V_INT:
|
||||
vstr = "int";
|
||||
break;
|
||||
case V_SHORT:
|
||||
vstr = "short";
|
||||
break;
|
||||
case V_FLOAT:
|
||||
vstr = "float";
|
||||
break;
|
||||
case V_DOUBLE:
|
||||
vstr = "double";
|
||||
break;
|
||||
case V_STRING:
|
||||
vstr = "char";
|
||||
break;
|
||||
case V_EVFLAG:
|
||||
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");
|
||||
else
|
||||
printf(";\n");
|
||||
}
|
||||
}
|
||||
printf("} %s;\n", vname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate definition C code (C code in definition section) */
|
||||
gen_defn_c_code()
|
||||
{
|
||||
extern LIST defn_c_list;
|
||||
Action *ap;
|
||||
|
||||
ap = firstAction(&defn_c_list);
|
||||
if (ap != NULL)
|
||||
{
|
||||
printf("\n\t/* C code definitions */\n");
|
||||
for (; ap != NULL; ap = nextAction(ap))
|
||||
{
|
||||
print_line_num(ap->line_num);
|
||||
printf("%s\n", ap->stmt.c_code);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate the structure with data for a state program table (SPROG) */
|
||||
gen_state_prog_table()
|
||||
{
|
||||
extern char *prog_param;
|
||||
|
||||
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))
|
||||
{
|
||||
/* Only process db variables */
|
||||
if (cp->db_name != NULL)
|
||||
{
|
||||
if (nchan > 0)
|
||||
printf(",\n");
|
||||
fill_db_block(cp);
|
||||
nchan++;
|
||||
}
|
||||
}
|
||||
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;
|
||||
int nchan;
|
||||
Chan *cp;
|
||||
|
||||
nchan = 0;
|
||||
for (cp = firstChan(&chan_list); cp != NULL; cp = nextChan(cp))
|
||||
{
|
||||
if (cp->db_name != NULL)
|
||||
{
|
||||
cp->index = nchan;
|
||||
nchan++;
|
||||
}
|
||||
}
|
||||
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_ef_bits()
|
||||
{
|
||||
extern LIST var_list;
|
||||
Var *vp;
|
||||
int ef_num;
|
||||
|
||||
ef_num = 0;
|
||||
printf("\n/* Event flags */\n");
|
||||
for (vp = firstVar(&var_list); vp != NULL; vp = nextVar(vp))
|
||||
{
|
||||
if (vp->type == V_EVFLAG)
|
||||
{
|
||||
vp->ef_num = ef_num;
|
||||
printf("#define %s (1<<%d)\n", vp->name, ef_num);
|
||||
ef_num++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
152
src/sequencer/seq_ca.c
Normal file
152
src/sequencer/seq_ca.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_ca.c 1.7 2/4/91
|
||||
DESCRIPTION: Seq_ca.c: Channel access interface for sequencer
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
***************************************************************************/
|
||||
|
||||
#include "seq.h"
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
|
||||
#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;
|
||||
{
|
||||
CHAN *db_ptr;
|
||||
int status, i;
|
||||
|
||||
/* Initialize CA task */
|
||||
ca_task_initialize();
|
||||
|
||||
/* 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,
|
||||
macro_tbl);
|
||||
printf(" %d: %s\n", i, db_ptr->db_name);
|
||||
status = ca_search(db_ptr->db_name, &(db_ptr->chid));
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_search");
|
||||
ca_task_exit();
|
||||
return -1;
|
||||
}
|
||||
db_ptr++;
|
||||
}
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
db_ptr++;
|
||||
}
|
||||
ca_flush_io();
|
||||
|
||||
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;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
db_ptr = (CHAN *)args.usr;
|
||||
/* 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
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
if (ss_ptr->action_complete)
|
||||
{
|
||||
semGive(ss_ptr->sem_id);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
288
src/sequencer/seq_mac.c
Normal file
288
src/sequencer/seq_mac.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_mac.c 1.1 11/9/90
|
||||
DESCRIPTION: Macro routines for Sequencer.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "vxWorks.h"
|
||||
#include "seq.h"
|
||||
|
||||
LOCAL int macNameLth();
|
||||
LOCAL int macParseName();
|
||||
LOCAL int macParseValue();
|
||||
LOCAL char *skipBlanks();
|
||||
|
||||
|
||||
|
||||
/* #define DEBUG */
|
||||
|
||||
/* macTblInit - initialize macro table */
|
||||
macTblInit(mac_ptr)
|
||||
MACRO *mac_ptr;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < MAX_MACROS; i++, mac_ptr++)
|
||||
{
|
||||
mac_ptr->name = NULL;
|
||||
mac_ptr->value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* macEval - substitute macro value into a string */
|
||||
macEval(pInStr, pOutStr, maxChar, macTbl)
|
||||
char *pInStr;
|
||||
char *pOutStr;
|
||||
MACRO *macTbl;
|
||||
{
|
||||
char *pMacVal, *pTmp;
|
||||
int nameLth, valLth;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("macEval: InStr=%s\n", pInStr);
|
||||
#endif
|
||||
pTmp = pOutStr;
|
||||
while (*pInStr != 0 && maxChar > 0)
|
||||
{
|
||||
if (*pInStr == '{')
|
||||
{ /* Macro substitution */
|
||||
pInStr++; /* points to macro name */
|
||||
nameLth = macNameLth(pInStr);
|
||||
#ifdef DEBUG
|
||||
printf("Name=%s[%d]\n", pInStr, nameLth);
|
||||
#endif
|
||||
/* Find macro value from macro name */
|
||||
pMacVal = macValGet(pInStr, nameLth, macTbl);
|
||||
if (pMacVal != NULL)
|
||||
{ /* Substitute macro value */
|
||||
valLth = strlen(pMacVal);
|
||||
if (valLth > maxChar)
|
||||
valLth = maxChar;
|
||||
#ifdef DEBUG
|
||||
printf("Val=%s[%d]\n", pMacVal, valLth);
|
||||
#endif
|
||||
strncpy(pOutStr, pMacVal, valLth);
|
||||
maxChar -= valLth;
|
||||
pOutStr += valLth;
|
||||
}
|
||||
pInStr += nameLth;
|
||||
if (*pInStr != 0)
|
||||
pInStr++; /* skip '}' */
|
||||
|
||||
}
|
||||
else
|
||||
{ /* Straight susbstitution */
|
||||
*pOutStr++ = *pInStr++;
|
||||
maxChar--;
|
||||
}
|
||||
*pOutStr = 0;
|
||||
#ifdef DEBUG
|
||||
printf("OutStr=%s\n", pTmp);
|
||||
#endif
|
||||
}
|
||||
*pOutStr == 0;
|
||||
}
|
||||
|
||||
/* macValGet - given macro name, return pointer to its value */
|
||||
char *macValGet(macName, macNameLth, macTbl)
|
||||
char *macName;
|
||||
int macNameLth;
|
||||
MACRO *macTbl;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < MAX_MACROS; i++, macTbl++)
|
||||
{
|
||||
if ((macTbl->name != NULL) &&
|
||||
(strlen(macTbl->name) == macNameLth))
|
||||
{
|
||||
if (strncmp(macName, macTbl->name, macNameLth) == 0)
|
||||
{
|
||||
return macTbl->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return number of characters in a macro name */
|
||||
LOCAL int macNameLth(pstr)
|
||||
char *pstr;
|
||||
{
|
||||
int nchar;
|
||||
|
||||
nchar = 0;
|
||||
while ( (*pstr != 0) && (*pstr != '}') )
|
||||
{
|
||||
pstr++;
|
||||
nchar++;
|
||||
}
|
||||
return nchar;
|
||||
}
|
||||
/* macParse - 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 nMac, nChar;
|
||||
char *skipBlanks();
|
||||
MACRO *pMacTbl;
|
||||
char *name, *value;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
/* Skip blanks */
|
||||
pMacStr = skipBlanks(pMacStr);
|
||||
|
||||
/* Parse the macro name */
|
||||
|
||||
nChar = macParseName(pMacStr);
|
||||
if (nChar == 0)
|
||||
break; /* finished or error */
|
||||
name = seqAlloc(nChar+1);
|
||||
if (name == NULL)
|
||||
break;
|
||||
bcopy(pMacStr, name, nChar);
|
||||
name[nChar] = 0;
|
||||
#ifdef DEBUG
|
||||
printf("name=%s, nChar=%d\n", name, nChar);
|
||||
#endif
|
||||
pMacStr += nChar;
|
||||
|
||||
/* Find a slot in the table */
|
||||
pMacTbl = macTblGet(name, macTbl);
|
||||
if (pMacTbl == NULL)
|
||||
break; /* table is full */
|
||||
if (pMacTbl->name == NULL)
|
||||
{ /* Empty slot, insert macro name */
|
||||
pMacTbl->name = name;
|
||||
}
|
||||
|
||||
/* Skip over blanks and equal sign or comma */
|
||||
pMacStr = skipBlanks(pMacStr);
|
||||
if (*pMacStr == ',')
|
||||
{ /* no value after the macro name */
|
||||
pMacStr++;
|
||||
continue;
|
||||
}
|
||||
if (*pMacStr++ != '=')
|
||||
break;
|
||||
pMacStr = skipBlanks(pMacStr);
|
||||
|
||||
/* Parse the value */
|
||||
nChar = macParseValue(pMacStr);
|
||||
if (nChar == 0)
|
||||
break;
|
||||
value = seqAlloc(nChar+1);
|
||||
if (value == NULL)
|
||||
break;
|
||||
bcopy(pMacStr, value, nChar);
|
||||
value[nChar] = 0;
|
||||
pMacStr += nChar;
|
||||
#ifdef DEBUG
|
||||
printf("value=%s, nChar=%d\n", value, nChar);
|
||||
#endif
|
||||
|
||||
/* Insert or replace macro value */
|
||||
pMacTbl->value = value;
|
||||
|
||||
/* Skip blanks and comma */
|
||||
pMacStr = skipBlanks(pMacStr);
|
||||
if (*pMacStr++ != ',')
|
||||
break;
|
||||
}
|
||||
if (*pMacStr == 0)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
LOCAL int macParseName(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
int nChar;
|
||||
|
||||
/* First character must be [A-Z,a-z] */
|
||||
if (!isalpha(*pStr))
|
||||
return 0;
|
||||
pStr++;
|
||||
nChar = 1;
|
||||
/* Character must be [A-Z,a-z,0-9,_] */
|
||||
while ( isalnum(*pStr) || *pStr == '_' )
|
||||
{
|
||||
pStr++;
|
||||
nChar++;
|
||||
}
|
||||
/* Loop terminates on any non-name character */
|
||||
return nChar;
|
||||
}
|
||||
|
||||
LOCAL int macParseValue(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
int nChar;
|
||||
|
||||
nChar = 0;
|
||||
/* Character string terminates on blank, comma, or EOS */
|
||||
while ( (*pStr != ' ') && (*pStr != ',') && (*pStr != 0) )
|
||||
{
|
||||
pStr++;
|
||||
nChar++;
|
||||
}
|
||||
return nChar;
|
||||
}
|
||||
|
||||
LOCAL char *skipBlanks(pChar)
|
||||
char *pChar;
|
||||
{
|
||||
while (*pChar == ' ')
|
||||
pChar++;
|
||||
return pChar;
|
||||
}
|
||||
|
||||
/* macTblGet - find a match for the specified name, otherwise
|
||||
return an empty slot in macro table */
|
||||
LOCAL MACRO *macTblGet(name, macTbl)
|
||||
char *name; /* macro name */
|
||||
MACRO *macTbl;
|
||||
{
|
||||
int i;
|
||||
MACRO *pMacTbl;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("macTblGet: name=%s\n", name);
|
||||
#endif
|
||||
for (i = 0, pMacTbl = macTbl; i < MAX_MACROS; i++, pMacTbl++)
|
||||
{
|
||||
if (pMacTbl->name != NULL)
|
||||
{
|
||||
if (strcmp(name, pMacTbl->name) == 0)
|
||||
{
|
||||
return pMacTbl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found, find an empty slot */
|
||||
for (i = 0, pMacTbl = macTbl; i < MAX_MACROS; i++, pMacTbl++)
|
||||
{
|
||||
if (pMacTbl->name == NULL)
|
||||
{
|
||||
return pMacTbl;
|
||||
}
|
||||
}
|
||||
|
||||
/* No empty slots available */
|
||||
return NULL;
|
||||
}
|
||||
420
src/sequencer/seq_main.c
Normal file
420
src/sequencer/seq_main.c
Normal file
@@ -0,0 +1,420 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq.c 1.8 2/1/91
|
||||
DESCRIPTION: Seq() initiates a sequence as a group of cooperating
|
||||
tasks. An optional string parameter specifies the values for
|
||||
macros.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
***************************************************************************/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
#include "seq.h"
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
|
||||
#define SCRATCH_SIZE (MAX_MACROS*(MAX_STRING_SIZE+1)*12)
|
||||
|
||||
/* 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
|
||||
tasks.
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
{
|
||||
int status;
|
||||
extern sequencer(), sprog_delete();
|
||||
extern char *seqVersion;
|
||||
|
||||
/* If no parameters specified, print version info. */
|
||||
if (sp_ptr == 0)
|
||||
{
|
||||
printf("%s\n", seqVersion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for correct state program format */
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
{ /* Oops */
|
||||
printf("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);
|
||||
#endif DEBUG
|
||||
|
||||
/* Make "task_area_ptr" a task variable */
|
||||
if (taskVarAdd(tid, &task_area_ptr) != OK)
|
||||
{
|
||||
printf("taskVarAdd failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sp_ptr_orig->task_id = tid;
|
||||
sp_ptr = task_area_ptr->sp_ptr;
|
||||
mac_ptr = task_area_ptr->mac_ptr;
|
||||
|
||||
/* Make a private copy of original structures (but change pointers!) */
|
||||
copy_sprog(sp_ptr_orig, task_area_ptr);
|
||||
|
||||
/* Initialize state program block */
|
||||
init_sprog(sp_ptr);
|
||||
|
||||
/* Initialize state set control blocks */
|
||||
init_sscb(sp_ptr);
|
||||
|
||||
/* Initialize the macro definition table */
|
||||
macTblInit(mac_ptr); /* Init macro table */
|
||||
|
||||
/* Parse the macro definitions */
|
||||
macParse(macro_def, mac_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;
|
||||
#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);
|
||||
#endif DEBUG
|
||||
|
||||
return ta_ptr;
|
||||
}
|
||||
|
||||
/* Count the total number of states in ALL state sets */
|
||||
LOCAL count_states(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
int nss, nstates;
|
||||
|
||||
nstates = 0;
|
||||
ss_ptr = sp_ptr->sscb;
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++)
|
||||
{
|
||||
nstates += ss_ptr->num_states;
|
||||
}
|
||||
return nstates;
|
||||
}
|
||||
/* 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;
|
||||
{
|
||||
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;
|
||||
|
||||
sp_ptr = ta_ptr->sp_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;
|
||||
|
||||
/* Copy structures for each state set */
|
||||
for (nss = 0; nss < sp_ptr->nss; nss++)
|
||||
{
|
||||
*ss_ptr = *ss_ptr_orig; /* copy SSCB */
|
||||
ss_ptr->states = st_ptr; /* new ptr to 1-st STATE */
|
||||
st_ptr_orig = ss_ptr_orig->states;
|
||||
for (nstates = 0; nstates < ss_ptr->num_states; nstates++)
|
||||
{
|
||||
*st_ptr++ = *st_ptr_orig++; /* copy STATE struct */
|
||||
}
|
||||
ss_ptr++;
|
||||
ss_ptr_orig++;
|
||||
}
|
||||
|
||||
/* Copy database channel structures */
|
||||
db_ptr = ta_ptr->db_ptr;
|
||||
sp_ptr->channels = db_ptr;
|
||||
db_ptr_orig = sp_ptr_orig->channels;
|
||||
for (nchan = 0; nchan < sp_ptr->nchan; nchan++)
|
||||
{
|
||||
*db_ptr = *db_ptr_orig;
|
||||
db_ptr->sprog = sp_ptr;
|
||||
db_ptr++;
|
||||
db_ptr_orig++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Initialize state program block */
|
||||
LOCAL init_sprog(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
sp_ptr->sem_id = semCreate();
|
||||
semInit(sp_ptr->sem_id);
|
||||
sp_ptr->task_is_deleted = FALSE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize state set control blocks */
|
||||
LOCAL init_sscb(sp_ptr)
|
||||
SPROG *sp_ptr;
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
STATE *st_ptr;
|
||||
int nss;
|
||||
char task_name[20];
|
||||
|
||||
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->action_complete = TRUE;
|
||||
}
|
||||
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)
|
||||
int nChar;
|
||||
{
|
||||
char *pStr;
|
||||
extern TASK *task_area_ptr;
|
||||
|
||||
pStr = task_area_ptr->scr_ptr;
|
||||
/* round to even no. bytes */
|
||||
if ((nChar & 1) != 0)
|
||||
nChar++;
|
||||
if (task_area_ptr->scr_nleft >= nChar)
|
||||
{
|
||||
task_area_ptr->scr_ptr += nChar;
|
||||
task_area_ptr->scr_nleft -= nChar;
|
||||
return pStr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
91
src/sequencer/seq_qry.c
Normal file
91
src/sequencer/seq_qry.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_qry.c 1.3 11/9/90
|
||||
DESCRIPTION: Task querry & debug routines for run-time sequencer
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
***************************************************************************/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
#include "seq.h"
|
||||
#include "vxWorks.h"
|
||||
#include "taskLib.h"
|
||||
|
||||
/* querry the sequencer */
|
||||
seqQry(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;
|
||||
|
||||
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");
|
||||
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);
|
||||
|
||||
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);
|
||||
wait_rtn();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
wait_rtn()
|
||||
{
|
||||
char bfr;
|
||||
printf("Hit RETURN to continue\n");
|
||||
do {
|
||||
read(STD_IN, &bfr, 1);
|
||||
} while (bfr != '\n');
|
||||
}
|
||||
245
src/sequencer/seq_task.c
Normal file
245
src/sequencer/seq_task.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)seq_task.c 1.4 2/1/91
|
||||
DESCRIPTION: Seq_tasks.c: Task creation and control for sequencer
|
||||
state sets.
|
||||
|
||||
ENVIRONMENT: VxWorks
|
||||
***************************************************************************/
|
||||
|
||||
#include "seq.h"
|
||||
#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;
|
||||
{
|
||||
SSCB *ss_ptr;
|
||||
int nss;
|
||||
char task_name[2*TASK_NAME_SIZE+2];
|
||||
extern TASK *task_area_ptr;
|
||||
extern ss_entry();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
/* Task entry point for state sets */
|
||||
/* Provides main loop for state set processing (common, re-entrant code) */
|
||||
ss_entry(sp_ptr, ss_ptr)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
{
|
||||
BOOL ev_trig;
|
||||
STATE *st_ptr;
|
||||
ULONG delay, get_timeout();
|
||||
|
||||
/* Initialize all tasks except the main task */
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* On 1-st pass fall thru w/o wake up */
|
||||
semGive(ss_ptr->sem_id);
|
||||
|
||||
/* Loop until an event is triggered */
|
||||
do {
|
||||
/* 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);
|
||||
#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 */
|
||||
ss_ptr->action_complete = FALSE;
|
||||
st_ptr->action_func(sp_ptr, ss_ptr);
|
||||
|
||||
/* Change to next 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;
|
||||
ss_ptr->action_complete = TRUE;
|
||||
}
|
||||
}
|
||||
/* Initialize state-set tasks */
|
||||
LOCAL ss_task_init(sp_ptr, ss_ptr)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_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 */
|
||||
|
||||
/* Import Channel Access context from main task */
|
||||
ca_import(sp_ptr->task_id);
|
||||
|
||||
return;
|
||||
}
|
||||
/* Return time-out for semTake() */
|
||||
LOCAL ULONG get_timeout(ss_ptr)
|
||||
SSCB *ss_ptr;
|
||||
{
|
||||
int ndelay;
|
||||
ULONG time, timeout, tmin;
|
||||
|
||||
if (ss_ptr->ndelay == 0)
|
||||
return 0;
|
||||
|
||||
time = tickGet();
|
||||
tmin = 0;
|
||||
/* find lowest timeout that's not expired */
|
||||
for (ndelay = 0; ndelay < ss_ptr->ndelay; ndelay++)
|
||||
{
|
||||
timeout = ss_ptr->timeout[ndelay];
|
||||
if (time < timeout)
|
||||
{
|
||||
if (tmin == 0 || timeout < tmin)
|
||||
tmin = timeout;
|
||||
}
|
||||
}
|
||||
if (tmin != 0)
|
||||
tmin -= time; /* convert timeout to delay */
|
||||
return tmin;
|
||||
}
|
||||
/* Set-up for delay() on entering a state. This routine is called
|
||||
by the state program for each delay in the "when" statement */
|
||||
VOID seq_start_delay(sp_ptr, ss_ptr, delay_id, delay)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
int delay_id; /* delay id */
|
||||
float delay;
|
||||
{
|
||||
ss_ptr->timeout[delay_id] = ss_ptr->time + delay*60.0;
|
||||
delay_id += 1;
|
||||
if (delay_id > ss_ptr->ndelay)
|
||||
ss_ptr->ndelay = delay_id;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test for time-out expired */
|
||||
BOOL seq_test_delay(sp_ptr, ss_ptr, delay_id)
|
||||
SPROG *sp_ptr;
|
||||
SSCB *ss_ptr;
|
||||
int delay_id;
|
||||
{
|
||||
return (ss_ptr->time >= ss_ptr->timeout[delay_id]);
|
||||
}
|
||||
/* This task is run whenever ANY task in the system is deleted */
|
||||
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;
|
||||
|
||||
tid = pTcbX->taskId;
|
||||
/* Note: task_area_ptr is a task variable */
|
||||
val = taskVarGet(tid, &task_area_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;
|
||||
|
||||
/* Is this a real sequencer task? */
|
||||
if (sp_ptr->magic != MAGIC)
|
||||
{
|
||||
printf(" Not main state program task\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Delete 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 */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("free ta_ptr=0x%x\n", ta_ptr);
|
||||
taskDelay(60);
|
||||
free(ta_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* semTake - take semaphore:
|
||||
VxWorks semTake with timeout added. */
|
||||
LOCAL VOID semTake (semId, timeout)
|
||||
SEM_ID semId; /* semaphore id to take */
|
||||
UINT timeout; /* timeout in tics */
|
||||
{
|
||||
int dummy;
|
||||
|
||||
vrtxPend(&semId->count, timeout, &dummy);
|
||||
}
|
||||
239
src/sequencer/snc.y
Normal file
239
src/sequencer/snc.y
Normal file
@@ -0,0 +1,239 @@
|
||||
%{
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)snc.y 1.1 10/16/90
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
/* SNC - State Notation Compiler.
|
||||
* The general structure of a state program is:
|
||||
* program-name
|
||||
* declarations
|
||||
* ss { state { event { action ...} new-state } ... } ...
|
||||
*
|
||||
* The following yacc definitions call the various parsing routines, which
|
||||
* are coded in the file "parse.c". Their major action is to build
|
||||
* a structure for each SNL component (state, event, action, etc.) and
|
||||
* build linked lists from these structures. The linked lists have a
|
||||
* hierarchical structure corresponding to the SNL block structure.
|
||||
* For instance, a "state" structure is linked to a chain of "event",
|
||||
* structures, which are, in turn, linked to a chain of "action"
|
||||
* structures.
|
||||
* The lexical analyser (see snc_lax.l) reads the input
|
||||
* stream and passes tokens to the yacc-generated code. The snc_lex
|
||||
* and parsing routines may also pass data elements that take on one
|
||||
* of the types defined under the %union definition.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "parse.h"
|
||||
|
||||
Expr *expression();
|
||||
Expr *parameter();
|
||||
|
||||
extern int line_num; /* input file line no. */
|
||||
%}
|
||||
|
||||
%start state_program
|
||||
|
||||
%union
|
||||
{
|
||||
int ival;
|
||||
char *pchar;
|
||||
void *pval;
|
||||
Expr *expr;
|
||||
}
|
||||
%token <pchar> STATE STATE_SET
|
||||
%token <pchar> NUMBER NAME DBNAME
|
||||
%token <pchar> DEBUG_PRINT
|
||||
%token PROGRAM DEFINE
|
||||
%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 EVFLAG SYNC
|
||||
%token ASTERISK AMPERSAND
|
||||
%token PLUS MINUS SLASH GT GE EQ LE LT NE NOT
|
||||
%token PLUS_EQUAL MINUS_EQUAL MULT_EQUAL DIV_EQUAL AND_EQUAL OR_EQUAL
|
||||
%token <pchar> STRING
|
||||
%token <pchar> C_STMT
|
||||
%type <ival> type
|
||||
%type <pchar> subscript
|
||||
%type <expr> parameter function expression
|
||||
/* precidence rules for expression evaluation */
|
||||
%left OR AND
|
||||
%left GT GE EQ NE LE LT
|
||||
%left PLUS MINUS
|
||||
%left ASTERISK SLASH
|
||||
%left NOT UOP /* unary operators: e.g. -x */
|
||||
%left SUBSCRIPT
|
||||
|
||||
%% /* 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 /* program name */
|
||||
: PROGRAM NAME { program_name($2, ""); }
|
||||
| PROGRAM NAME L_PAREN STRING R_PAREN { program_name($2, $4); }
|
||||
;
|
||||
|
||||
definitions /* definitions block */
|
||||
: defn_stmt
|
||||
| definitions defn_stmt
|
||||
;
|
||||
|
||||
defn_stmt /* individual definitions for SNL (preceeds state sets) */
|
||||
: assign_stmt
|
||||
| monitor_stmt
|
||||
| decl_stmt
|
||||
| debug_stmt
|
||||
| sync_stmt
|
||||
| C_STMT { defn_c_stmt($1); }
|
||||
| error { snc_err("definitions", line_num, 1); }
|
||||
;
|
||||
|
||||
assign_stmt /* 'assign <var name>[<lower lim>,<upper lim>] to <db name>;' */
|
||||
/* subscript range is optional */
|
||||
: ASSIGN NAME TO STRING SEMI_COLON { assign_stmt($2, (char *)0, (char *)0, $4); }
|
||||
| ASSIGN NAME L_SQ_BRACKET NUMBER R_SQ_BRACKET TO STRING SEMI_COLON
|
||||
{ assign_stmt($2, $4, (char *)0, $7); }
|
||||
| ASSIGN NAME L_SQ_BRACKET NUMBER COMMA NUMBER R_SQ_BRACKET TO STRING SEMI_COLON
|
||||
{ assign_stmt($2, $4, $6, $9); }
|
||||
;
|
||||
|
||||
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); }
|
||||
;
|
||||
|
||||
subscript /* e.g. [10] */
|
||||
: /* empty */ { $$ = 0; }
|
||||
| L_SQ_BRACKET NUMBER R_SQ_BRACKET { $$ = $2; }
|
||||
;
|
||||
|
||||
debug_stmt
|
||||
: DEBUG_PRINT NUMBER SEMI_COLON { set_debug_print($2); }
|
||||
;
|
||||
|
||||
decl_stmt /* variable declarations (e.g. float x[20];) */
|
||||
: type NAME subscript SEMI_COLON { decl_stmt($1, $2, $3, (char *)0); }
|
||||
| type NAME subscript EQUAL NUMBER SEMI_COLON { decl_stmt($1, $2, $3, $5); }
|
||||
| type NAME subscript EQUAL STRING SEMI_COLON { decl_stmt($1, $2, $3, $5); }
|
||||
;
|
||||
|
||||
type /* types for variables defined in SNL */
|
||||
: FLOAT { $$ = V_FLOAT; }
|
||||
| DOUBLE { $$ = V_DOUBLE; }
|
||||
| INT { $$ = V_INT; }
|
||||
| SHORT { $$ = V_SHORT; }
|
||||
| CHAR { $$ = V_CHAR; }
|
||||
| STRING_DECL { $$ = V_STRING; }
|
||||
| EVFLAG { $$ = V_EVFLAG; }
|
||||
;
|
||||
|
||||
sync_stmt /* sync <variable> <event flag> */
|
||||
: SYNC NAME subscript NAME SEMI_COLON { sync_stmt($2, $3, $4); }
|
||||
| SYNC NAME subscript TO NAME SEMI_COLON { sync_stmt($2, $3, $5); }
|
||||
;
|
||||
|
||||
program_body /* a program body is one or more state sets */
|
||||
: state_set
|
||||
| program_body state_set
|
||||
;
|
||||
|
||||
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_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_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); }
|
||||
;
|
||||
|
||||
trans_list /* all transitions for one state */
|
||||
: transition
|
||||
| trans_list transition
|
||||
| error { snc_err("transition", line_num, 5); }
|
||||
;
|
||||
|
||||
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); }
|
||||
;
|
||||
|
||||
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
|
||||
{ $$ = expression(E_SUBSCR, "", $1, $3); }
|
||||
| /* empty */ { $$ = expression(E_EMPTY, ""); }
|
||||
;
|
||||
|
||||
function /* function */
|
||||
: NAME L_PAREN parameter R_PAREN { $$ = expression(E_FUNC, $1, (Expr *)0, $3); }
|
||||
;
|
||||
|
||||
parameter /* expr, expr, .... */
|
||||
: expression { $$ = parameter($1, 0); }
|
||||
| parameter COMMA expression { $$ = parameter($3, $1); }
|
||||
| /* empty */ { $$ = 0; }
|
||||
;
|
||||
|
||||
action /* action block for a single state */
|
||||
: /* Empty */
|
||||
| action_item
|
||||
| action action_item
|
||||
| error { snc_err("action", line_num, 8); }
|
||||
;
|
||||
|
||||
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); }
|
||||
;
|
||||
|
||||
%%
|
||||
164
src/sequencer/snc_lex.l
Normal file
164
src/sequencer/snc_lex.l
Normal file
@@ -0,0 +1,164 @@
|
||||
%{
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)snc_lex.l 1.1 10/16/90
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
/* Lexical analyzer for State Notation Compiler (snc).
|
||||
*
|
||||
* This routine recognizes State Notation Language (SNL) syntax,
|
||||
* and passes tokens to yacc().
|
||||
* All C code is passed through as a stream, without conversion.
|
||||
* Hence, the C compiler may find errors not reported by SNC.
|
||||
* Comments are recognized as part of the syntax.
|
||||
*/
|
||||
|
||||
#include "parse.h"
|
||||
#include "y.tab.h" /* output from yacc */
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#define RETURN(param) { printf("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;
|
||||
|
||||
%}
|
||||
|
||||
/* Start conditions (SNL, C code, comment, and string) */
|
||||
%Start SNL C_CODE COMMENT STR
|
||||
|
||||
NAME [a-zA-Z][a-zA-Z0-9_]*
|
||||
FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
|
||||
%% /* Begin rules */
|
||||
<C_CODE>. *str_next++ = yytext[0];
|
||||
<C_CODE>\n {
|
||||
*str_next++ = '\n';
|
||||
line_num++;
|
||||
if (one_line_c_code)
|
||||
{
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
}
|
||||
<C_CODE>"}%" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
<COMMENT>\n line_num++;
|
||||
<COMMENT>"*/" BEGIN SNL;
|
||||
<COMMENT>. ;
|
||||
<STR>"\\\"" {
|
||||
*str_next++ = yytext[0];
|
||||
*str_next++ = yytext[1];
|
||||
}
|
||||
<STR>\" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(STRING);
|
||||
}
|
||||
<STR>. { *str_next++ = yytext[0]; }
|
||||
<STR>\n { *str_next++ = '?'; line_num++; }
|
||||
<SNL>\n { line_num++; }
|
||||
<SNL>"%{" {
|
||||
c_str = str_next;
|
||||
one_line_c_code = FALSE;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>"%%" {
|
||||
c_str = str_next;
|
||||
one_line_c_code = TRUE;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>"/*" BEGIN COMMENT;
|
||||
<SNL>\" { c_str = str_next; BEGIN STR; }
|
||||
<SNL>"ss" RETURN(STATE_SET);
|
||||
<SNL>"state" RETURN(STATE);
|
||||
<SNL>"when" RETURN(WHEN);
|
||||
<SNL>"monitor" RETURN(MONITOR);
|
||||
<SNL>"assign" RETURN(ASSIGN);
|
||||
<SNL>"int" RETURN(INT);
|
||||
<SNL>"float" RETURN(FLOAT);
|
||||
<SNL>"double" RETURN(DOUBLE);
|
||||
<SNL>"short" RETURN(SHORT);
|
||||
<SNL>"char" RETURN(CHAR);
|
||||
<SNL>"string" RETURN(STRING_DECL);
|
||||
<SNL>"to" RETURN(TO);
|
||||
<SNL>"define" RETURN(DEFINE);
|
||||
<SNL>"program" RETURN(PROGRAM);
|
||||
<SNL>"debug" RETURN(DEBUG_PRINT);
|
||||
<SNL>"evflag" RETURN(EVFLAG);
|
||||
<SNL>"sync" RETURN(SYNC);
|
||||
<SNL>{NAME} {
|
||||
nc = strlen(yytext);
|
||||
bcopy(yytext, str_next, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
RETURN(NAME);
|
||||
}
|
||||
<SNL>\= RETURN(EQUAL);
|
||||
<SNL>\: RETURN(COLON);
|
||||
<SNL>\& RETURN(AMPERSAND);
|
||||
<SNL>\* RETURN(ASTERISK);
|
||||
<SNL>\{ RETURN(L_BRACKET);
|
||||
<SNL>\} RETURN(R_BRACKET);
|
||||
<SNL>\[ RETURN(L_SQ_BRACKET);
|
||||
<SNL>\] RETURN(R_SQ_BRACKET);
|
||||
<SNL>\; RETURN(SEMI_COLON);
|
||||
<SNL>\. RETURN(PERIOD);
|
||||
<SNL>\( RETURN(L_PAREN);
|
||||
<SNL>\) RETURN(R_PAREN);
|
||||
<SNL>\, RETURN(COMMA);
|
||||
<SNL>"|" RETURN(OR);
|
||||
<SNL>"&" RETURN(AND);
|
||||
<SNL>"||" RETURN(OR);
|
||||
<SNL>"&&" RETURN(AND);
|
||||
<SNL>"+" RETURN(PLUS);
|
||||
<SNL>"-" RETURN(MINUS);
|
||||
<SNL>"/" RETURN(SLASH);
|
||||
<SNL>">" RETURN(GT);
|
||||
<SNL>">=" RETURN(GE);
|
||||
<SNL>"==" RETURN(EQ);
|
||||
<SNL>"+=" RETURN(PLUS_EQUAL);
|
||||
<SNL>"-=" RETURN(MINUS_EQUAL);
|
||||
<SNL>"*=" RETURN(MULT_EQUAL);
|
||||
<SNL>"/=" RETURN(DIV_EQUAL);
|
||||
<SNL>"&=" RETURN(AND_EQUAL);
|
||||
<SNL>"|=" RETURN(OR_EQUAL);
|
||||
<SNL>"!=" RETURN(NE);
|
||||
<SNL>"<=" RETURN(LE);
|
||||
<SNL>"<" RETURN(LT);
|
||||
<SNL>"!" RETURN(NOT);
|
||||
<SNL>{FPNUM} {
|
||||
nc = strlen(yytext);
|
||||
bcopy(yytext, str_next, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<SNL>[\t\ ]* ;
|
||||
<SNL>. RETURN(BAD_CHAR);
|
||||
.|\n { line_num = 1; BEGIN SNL; yyless(0); }
|
||||
|
||||
194
src/sequencer/snc_main.c
Normal file
194
src/sequencer/snc_main.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
@(#)snc_main.c 1.1 10/16/90
|
||||
DESCRIPTION: Main program and miscellaneous routines for
|
||||
State Notation Compiler.
|
||||
|
||||
ENVIRONMENT: UNIX
|
||||
***************************************************************************/
|
||||
extern char *sncVersion;
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* SNC Globals: */
|
||||
int line_no = 1; /* input line number */
|
||||
char in_file[200]; /* input file name */
|
||||
char out_file[200]; /* output file name */
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: main
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* -------------------------------------------------------------
|
||||
* int argc I arg count
|
||||
* char *argv[] I array of ptrs to args
|
||||
*
|
||||
* RETURNS: n/a
|
||||
*
|
||||
* FUNCTION: Program entry.
|
||||
*
|
||||
* NOTES: The streams stdin and stdout are redirected to files named in the
|
||||
* command parameters. This accomodates the use by lex of stdin for input
|
||||
* and permits printf() to be used for output. Stderr is not redirected.
|
||||
*
|
||||
* This routine calls yyparse(), which never returns.
|
||||
*-*************************************************************************/
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
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)
|
||||
{
|
||||
perror(in_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#define REDIRECT
|
||||
#ifdef REDIRECT
|
||||
/* Redirect output stream to specified file */
|
||||
outfp = freopen(out_file, "w", stdout);
|
||||
if (outfp == NULL)
|
||||
{
|
||||
perror(out_file);
|
||||
exit(1);
|
||||
}
|
||||
#endif REDIRECT
|
||||
printf(
|
||||
"/* %s: %s */\n\n", sncVersion, in_file);
|
||||
|
||||
/* Initialize parser */
|
||||
init_snc();
|
||||
|
||||
/* Call the SNC parser */
|
||||
yyparse();
|
||||
}
|
||||
/*+************************************************************************
|
||||
* NAME: get_args
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* -----------------------------------------------------------
|
||||
* int argc I number of arguments
|
||||
* char *argv[] I shell command arguments
|
||||
* RETURNS: n/a
|
||||
*
|
||||
* FUNCTION: Get the shell command arguments.
|
||||
*
|
||||
* NOTES: If "*.s" is input file then "*.c" is the output file. Otherwise,
|
||||
* ".c" is appended to the input file to form the output file name.
|
||||
* Sets the gloabals in_file[] and out_file[].
|
||||
*-*************************************************************************/
|
||||
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");
|
||||
exit(1);
|
||||
}
|
||||
s = argv[1];
|
||||
|
||||
ls = strlen(s);
|
||||
bcopy(s, in_file, ls);
|
||||
in_file[ls] = 0;
|
||||
bcopy(s, out_file, ls);
|
||||
if ( strcmp(&in_file[ls-3], ".st") == 0 )
|
||||
{
|
||||
out_file[ls-2] = 'c';
|
||||
out_file[ls-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
out_file[ls] = '.';
|
||||
out_file[ls+1] = 'c';
|
||||
ls += 2;
|
||||
}
|
||||
out_file[ls] = 0;
|
||||
return;
|
||||
}
|
||||
/*+************************************************************************
|
||||
* NAME: snc_err
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* -------------------------------------------------------------------
|
||||
* char *err_txt I Text of error msg.
|
||||
* int line I Line no. where error ocurred
|
||||
* int code I Error code (see snc.y)
|
||||
*
|
||||
* RETURNS: no return
|
||||
*
|
||||
* FUNCTION: Print the SNC error message and then exit.
|
||||
*
|
||||
* NOTES:
|
||||
*-*************************************************************************/
|
||||
snc_err(err_txt, line, code)
|
||||
char *err_txt;
|
||||
int line, code;
|
||||
{
|
||||
fprintf(stderr, "Syntax error %d (%s) at line %d\n",
|
||||
code, err_txt, line);
|
||||
exit(code);
|
||||
}
|
||||
/*+************************************************************************
|
||||
* NAME: yyerror
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* ---------------------------------------------------
|
||||
* char *err I yacc error
|
||||
*
|
||||
* RETURNS: n/a
|
||||
*
|
||||
* FUNCTION: Print yacc error msg
|
||||
*
|
||||
* NOTES:
|
||||
*-*************************************************************************/
|
||||
yyerror(err)
|
||||
char *err;
|
||||
{
|
||||
fprintf(stderr, "%s: line no. %d\n", err, line_no);
|
||||
return;
|
||||
}
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: print_line_num
|
||||
*
|
||||
* CALLING SEQUENCE
|
||||
* type argument I/O description
|
||||
* ---------------------------------------------------
|
||||
* int line_num I current line number
|
||||
*
|
||||
* RETURNS: n/a
|
||||
*
|
||||
* FUNCTION: Prints the line number and input file name for use by the
|
||||
* C preprocessor. e.g.: # line 24 "something.st"
|
||||
*
|
||||
* NOTES:
|
||||
*-*************************************************************************/
|
||||
print_line_num(line_num)
|
||||
int line_num;
|
||||
{
|
||||
printf("# line %d \"%s\"\n", line_num, in_file);
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user