moved to src/vxWorks

This commit is contained in:
Marty Kraimer
1999-11-18 15:55:58 +00:00
parent 567dde3e14
commit f91da5d830
24 changed files with 0 additions and 7115 deletions
-51
View File
@@ -1,51 +0,0 @@
TOP=../..
include $(TOP)/configure/CONFIG
#YACCOPT = -l
#LEXOPT = -L
#USR_LDLIBS = -ll
YACCOPT = -d -v
SYS_PROD_LIBS_DEFAULT := m
SYS_PROD_LIBS_WIN32 := -nil-
INC += seq.h
INC += seqCom.h
SRCS += snc_main.c
SRCS += parse.c
SRCS += phase2.c
SRCS += gen_ss_code.c
SRCS += gen_tables.c
SRCS += sncVersion.c
SRCS += snc.c
PROD_DEFAULT += snc
PROD_vxWorks +=
seq_CFLAGS =
seq_SRCS = \
seq_main.c seq_ca.c seq_qry.c seq_task.c \
seq_mac.c seq_prog.c seq_if.c seqVersion.c
LIBRARY_vxWorks = seq
include $(TOP)/configure/RULES_BUILD
#
# The generated lex file includes snc.h
#
snc.c: snc_lex.c
sncVersion.c: ../Version ../makeVersion.pl
$(PERL) ../makeVersion.pl ../Version sncVersion
clean::
@$(RM) y.output sncVersion.c snc_lex.c snc.c snc.h
seqVersion.c: ../Version ../makeVersion.pl
$(PERL) ../makeVersion.pl ../Version seqVersion
-6
View File
@@ -1,6 +0,0 @@
###
### 3 Apr. 1991 (MDA) moved seq.c to seq_main.c for consistency with
### snc, and for ease of use in Imakefiles...
###
### 03jan92,ajk s_*.c files are VxWorks version 5 compatable.
###
-1
View File
@@ -1 +0,0 @@
1.9.2.Beta12
-45
View File
@@ -1,45 +0,0 @@
#!/bin/sh
# epics/release chmod.sh,v 1.1.1.1 1995/08/15 03:15:26 epicss Exp
# Author: Roger A. Cole (LANL)
# Date: 08-20-91
#
# Experimental Physics and Industrial Control System (EPICS)
#
# Copyright 1991, the Regents of the University of California,
# and the University of Chicago Board of Governors.
#
# This software was produced under U.S. Government contracts:
# (W-7405-ENG-36) at the Los Alamos National Laboratory,
# and (W-31-109-ENG-38) at Argonne National Laboratory.
#
# Initial development by:
# The Controls and Automation Group (AT-8)
# Ground Test Accelerator
# Accelerator Technology Division
# Los Alamos National Laboratory
#
# Co-developed with
# The Controls and Computing Group
# Accelerator Systems Division
# Advanced Photon Source
# Argonne National Laboratory
#
# Modification Log:
# -----------------
# .01 08-20-91 rac initial version
# set execute permission for shell scripts in this directory (this avoids
# the need to manually maintain a list of file names)
# the name of this file is magic for ~epics/release/sccsGet. Whenever that
# that script sees a file named "chmod.sh" it executes the file.
L=""
for F in `find * \( -type d -prune \) -o -type f -print`; do
if [ "`sed -n -e '/^\#\!/p' -e 1q $F`" ]; then
L="$L $F"
fi
done
if [ "$L" ]; then
chmod +x $L
fi
-687
View File
@@ -1,687 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
gen_ss_code.c,v 1.2 1995/06/27 15:25:43 wright Exp
DESCRIPTION: gen_ss_code.c -- routines to generate state set code
ENVIRONMENT: UNIX
HISTORY:
19nov91,ajk Changed find_var() to findVar().
28apr92,ajk Implemented efClear() & efTestAndClear().
01mar94,ajk Changed table generation to the new structures defined
in seqCom.h.
13jan98,wfl Fixed handling of compound expressions, using E_COMMA.
***************************************************************************/
#include <stdio.h>
#include "parse.h"
#include "cadef.h"
#include <dbDefs.h>
#include <seqCom.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 DEBUG 1*/
#define EVENT_STMT 1
#define ACTION_STMT 2
#define DELAY_STMT 3
#define EXIT_STMT 4
gen_ss_code()
{
extern Expr *ss_list;
Expr *ssp;
Expr *sp;
/* For each state set ... */
for (ssp = ss_list; ssp != NULL; ssp = ssp->next)
{
/* For each state ... */
for (sp = ssp->left; sp != NULL; sp = sp->next)
{
printf("\f/* Code for state \"%s\" in state set \"%s\" */\n",
sp->value, ssp->value);
/* Generate function to set up for delay processing */
gen_delay_func(sp, ssp);
/* Generate event processing function */
gen_event_func(sp, ssp);
/* Generate action processing function */
gen_action_func(sp, ssp);
}
}
/* Generate exit handler code */
gen_exit_handler();
}
/* Generate a function for each state that sets up delay processing:
* This function gets called prior to the event function to guarantee
* that the initial delay value specified in delay() calls are used.
* Each delay() call is assigned a unique id. The maximum number of
* delays is recorded in the state set structure.
*/
gen_delay_func(sp, ssp)
Expr *ssp;
Expr *sp;
{
Expr *tp;
int eval_delay();
printf("\n/* Delay function for state \"%s\" in state set \"%s\" */\n",
sp->value, ssp->value);
printf("static void D_%s_%s(ssId, pVar)\n", ssp->value, sp->value);
printf("SS_ID\tssId;\n");
printf("struct UserVar\t*pVar;\n{\n");
/* For each transition: */
for (tp = sp->left; tp != NULL; tp = tp->next)
{
print_line_num(tp->line_num, tp->src_file);
traverseExprTree(tp, E_FUNC, "delay", eval_delay, sp);
}
printf("}\n");
}
/* Evaluate the expression within a delay() function and generate
* a call to seq_delayInit(). Adds ssId, delay id parameters and cast to float.
* Example: seq_delayInit(ssId, 1, (float)(<some expression>));
*/
eval_delay(ep, sp)
Expr *ep;
Expr *sp;
{
Expr *epf;
int delay_id;
extern char *stype[];
#ifdef DEBUG
fprintf(stderr, "eval_delay: type=%s\n", stype[ep->type]);
#endif /*DEBUG*/
/* Generate 1-st part of function w/ 1-st 2 parameters */
delay_id = (int)ep->right; /* delay id was previously assigned */
printf("\tseq_delayInit(ssId, %d, (", delay_id);
/* Evaluate & generate the 3-rd parameter (an expression) */
eval_expr(EVENT_STMT, ep->left, sp, 0);
/* Complete the function call */
printf("));\n");
}
/* 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)
Expr *sp;
Expr *ssp; /* Parent state set */
{
Expr *tp;
Expr *ap;
int trans_num;
extern char *prog_name;
extern line_num;
/* Action function declaration */
printf("\n/* Action function for state \"%s\" in state set \"%s\" */\n",
sp->value, ssp->value);
printf("static void A_%s_%s(ssId, pVar, transNum)\n",
ssp->value, sp->value);
printf("SS_ID\tssId;\n");
printf("struct UserVar\t*pVar;\n");
printf("short\ttransNum;\n{\n");
/* "switch" statment based on the transition number */
printf("\tswitch(transNum)\n\t{\n");
trans_num = 0;
line_num = 0;
/* For each transition ("when" statement) ... */
for (tp = sp->left; tp != NULL; tp = tp->next)
{
/* "case" for each transition */
printf("\tcase %d:\n", trans_num);
/* For each action statement insert action code */
for (ap = tp->right; ap != NULL; ap = ap->next)
{
if (line_num != ap->line_num)
{
print_line_num(ap->line_num, ap->src_file);
line_num = ap->line_num;
}
/* Evaluate statements */
eval_expr(ACTION_STMT, ap, sp, 2);
}
/* 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)
Expr *sp;
Expr *ssp;
{
Expr *tp;
int index, trans_num;
printf("\n/* Event function for state \"%s\" in state set \"%s\" */\n",
sp->value, ssp->value);
printf("static long E_%s_%s(ssId, pVar, pTransNum, pNextState)\n",
ssp->value, sp->value);
printf("SS_ID\tssId;\n");
printf("struct UserVar\t*pVar;\n");
printf("short\t*pTransNum, *pNextState;\n{\n");
trans_num = 0;
/* For each transition generate an "if" statement ... */
for (tp = sp->left; tp != NULL; tp = tp->next)
{
print_line_num(tp->line_num, tp->src_file);
printf("\tif (");
if (tp->left == 0)
printf("TRUE");
else
eval_expr(EVENT_STMT, tp->left, sp, 0);
printf(")\n\t{\n");
/* index is the transition number (0, 1, ...) */
index = state_block_index_from_name(ssp, tp->value);
if (index < 0)
{
fprintf(stderr, "Line %d: ", tp->line_num);
fprintf(stderr, "No state %s in state set %s\n",
tp->value, ssp->value);
index = 0; /* default to 1-st state */
printf("\t\t/* state %s does not exist */\n",
tp->value);
}
printf("\t\t*pNextState = %d;\n", index);
printf("\t\t*pTransNum = %d;\n", trans_num);
printf("\t\treturn TRUE;\n\t}\n");
trans_num++;
}
printf("\treturn FALSE;\n");
printf("}\n");
}
/* Given a state name and state set struct, find the corresponding
state struct and return its index (1-st one is 0) */
state_block_index_from_name(ssp, state_name)
Expr *ssp;
char *state_name;
{
Expr *sp;
int index;
index = 0;
for (sp = ssp->left; sp != NULL; sp = sp->next)
{
if (strcmp(state_name, sp->value) == 0)
return index;
index++;
}
return -1; /* State name non-existant */
}
/* Evaluate an expression.
*/
eval_expr(stmt_type, ep, sp, level)
int stmt_type; /* EVENT_STMT, ACTION_STMT, or DELAY_STMT */
Expr *ep; /* ptr to expression */
Expr *sp; /* ptr to current State struct */
int level; /* indentation level */
{
Expr *epf;
int nexprs;
extern int reent_opt;
extern int line_num;
if (ep == 0)
return;
switch(ep->type)
{
case E_CMPND:
indent(level);
printf("{\n");
line_num += 1;
for (epf = ep->left; epf != 0; epf = epf->next)
{
eval_expr(stmt_type, epf, sp, level+1);
}
indent(level);
printf("}\n");
line_num += 1;
break;
case E_STMT:
indent(level);
eval_expr(stmt_type, ep->left, sp, 0);
printf(";\n");
line_num += 1;
break;
case E_IF:
case E_WHILE:
indent(level);
if (ep->type == E_IF)
printf("if (");
else
printf("while (");
eval_expr(stmt_type, ep->left, sp, 0);
printf(")\n");
line_num += 1;
epf = ep->right;
if (epf->type == E_CMPND)
eval_expr(stmt_type, ep->right, sp, level);
else
eval_expr(stmt_type, ep->right, sp, level+1);
break;
case E_FOR:
indent(level);
printf("for (");
eval_expr(stmt_type, ep->left->left, sp, 0);
printf("; ");
eval_expr(stmt_type, ep->left->right, sp, 0);
printf("; ");
eval_expr(stmt_type, ep->right->left, sp, 0);
printf(")\n");
line_num += 1;
epf = ep->right->right;
if (epf->type == E_CMPND)
eval_expr(stmt_type, epf, sp, level);
else
eval_expr(stmt_type, epf, sp, level+1);
break;
case E_ELSE:
indent(level);
printf("else\n");
line_num += 1;
epf = ep->left;
/* Is it "else if" ? */
if (epf->type == E_IF || epf->type == E_CMPND)
eval_expr(stmt_type, ep->left, sp, level);
else
eval_expr(stmt_type, ep->left, sp, level+1);
break;
case E_VAR:
#ifdef DEBUG
fprintf(stderr, "E_VAR: %s\n", ep->value);
#endif /*DEBUG*/
if(reent_opt)
{ /* Make variables point to allocated structure */
Var *vp;
vp = (Var *)ep->left;
if (vp->type != V_NONE && vp->type != V_EVFLAG)
printf("(pVar->%s)", ep->value);
else
printf("%s", ep->value);
}
else
printf("%s", ep->value);
break;
case E_CONST:
printf("%s", ep->value);
break;
case E_STRING:
printf("\"%s\"", ep->value);
break;
case E_BREAK:
indent(level);
printf("break;\n");
line_num += 1;
break;
case E_FUNC:
#ifdef DEBUG
fprintf(stderr, "E_FUNC: %s\n", ep->value);
#endif /*DEBUG*/
if (special_func(stmt_type, ep, sp))
break;
printf("%s(", ep->value);
eval_expr(stmt_type, ep->left, sp, 0);
printf(") ");
break;
case E_COMMA:
for (epf = ep->left, nexprs = 0; epf != 0; epf = epf->next, nexprs++)
{
if (nexprs > 0)
printf(" ,");
eval_expr(stmt_type, epf, sp, 0);
}
break;
case E_ASGNOP:
case E_BINOP:
eval_expr(stmt_type, ep->left, sp, 0);
printf(" %s ", ep->value);
eval_expr(stmt_type, ep->right, sp, 0);
break;
case E_PAREN:
printf("(");
eval_expr(stmt_type, ep->left, sp, 0);
printf(")");
break;
case E_UNOP:
printf("%s", ep->value);
eval_expr(stmt_type, ep->left, sp, 0);
break;
case E_PRE:
printf("%s", ep->value);
eval_expr(stmt_type, ep->left, sp, 0);
break;
case E_POST:
eval_expr(stmt_type, ep->left, sp, 0);
printf("%s", ep->value);
break;
case E_SUBSCR:
eval_expr(stmt_type, ep->left, sp, 0);
printf("[");
eval_expr(stmt_type, ep->right, sp, 0);
printf("]");
break;
case E_TEXT:
printf("%s\n", ep->left);
line_num += 1;
break;
default:
if (stmt_type == EVENT_STMT)
printf("TRUE"); /* empty event statement defaults to TRUE */
else
printf(" ");
break;
}
}
indent(level)
int level;
{
while (level-- > 0)
printf("\t");
}
/* func_name_to_code - convert function name to a code */
enum fcode { F_DELAY, F_EFSET, F_EFTEST, F_EFCLEAR, F_EFTESTANDCLEAR,
F_PVGET, F_PVPUT, F_PVTIMESTAMP, F_PVASSIGN,
F_PVMONITOR, F_PVSTOPMONITOR, F_PVCOUNT, F_PVINDEX,
F_PVSTATUS, F_PVSEVERITY, F_PVFLUSH, F_PVERROR, F_PVGETCOMPLETE,
F_PVASSIGNED, F_PVCONNECTED,
F_PVCHANNELCOUNT, F_PVCONNECTCOUNT, F_PVASSIGNCOUNT,
F_PVDISCONNECT, F_SEQLOG, F_MACVALUEGET, F_OPTGET,
F_NONE };
char *fcode_str[] = { "delay", "efSet", "efTest", "efClear", "efTestAndClear",
"pvGet", "pvPut", "pvTimeStamp", "pvAssign",
"pvMonitor", "pvStopMonitor", "pvCount", "pvIndex",
"pvStatus", "pvSeverity", "pvFlush", "pvError", "pvGetComplete",
"pvAssigned", "pvConnected",
"pvChannelCount", "pvConnectCount", "pvAssignCount",
"pvDisconnect", "seqLog", "macValueGet", "optGet",
NULL };
enum fcode func_name_to_code(fname)
char *fname;
{
int i;
for (i = 0; fcode_str[i] != NULL; i++)
{
if (strcmp(fname, fcode_str[i]) == 0)
return (enum fcode)i;
}
return F_NONE;
}
/* Process special function (returns TRUE if this is a special function)
Checks for one of the following special functions:
- event flag functions, e.g. pvSet()
- process variable functions, e.g. pvPut()
- delay()
- macVauleget()
- seqLog()
*/
special_func(stmt_type, ep, sp)
int stmt_type; /* ACTION_STMT or EVENT_STMT */
Expr *ep; /* ptr to function in the expression */
Expr *sp; /* current State struct */
{
char *fname; /* function name */
Expr *ep1, *ep2, *ep3; /* parameters */
Chan *cp;
Var *vp;
enum fcode func_code;
int delay_id;
fname = ep->value;
func_code = func_name_to_code(fname);
if (func_code == F_NONE)
return FALSE; /* not a special function */
#ifdef DEBUG
fprintf(stderr, "special_func: func_code=%d\n", func_code);
#endif /*DEBUG*/
switch (func_code)
{
case F_DELAY:
delay_id = (int)ep->right;
printf("seq_delay(ssId, %d)", delay_id);
return TRUE;
case F_EFSET:
case F_EFTEST:
case F_EFCLEAR:
case F_EFTESTANDCLEAR:
/* Event flag funtions */
gen_ef_func(stmt_type, ep, sp, fname, func_code);
return TRUE;
case F_PVPUT:
case F_PVGET:
case F_PVTIMESTAMP:
case F_PVGETCOMPLETE:
case F_PVSTATUS:
case F_PVSEVERITY:
case F_PVCONNECTED:
case F_PVASSIGNED:
case F_PVMONITOR:
case F_PVSTOPMONITOR:
case F_PVCOUNT:
case F_PVINDEX:
case F_PVDISCONNECT:
case F_PVASSIGN:
/* DB functions requiring a channel id */
gen_pv_func(stmt_type, ep, sp, fname, func_code);
return TRUE;
case F_PVFLUSH:
case F_PVERROR:
case F_PVCHANNELCOUNT:
case F_PVCONNECTCOUNT:
case F_PVASSIGNCOUNT:
/* DB functions NOT requiring a channel structure */
printf("seq_%s(ssId)", fname);
return TRUE;
case F_SEQLOG:
case F_MACVALUEGET:
case F_OPTGET:
/* Any funtion that requires adding ssID as 1st parameter.
* Note: name is changed by prepending "seq_". */
printf("seq_%s(ssId", fname);
/* now fill in user-supplied paramters */
ep1 = ep->left;
if (ep1 != 0 && ep1->type == E_COMMA)
ep1 = ep1->left;
for (; ep1 != 0; ep1 = ep1->next)
{
printf(", ");
eval_expr(stmt_type, ep1, sp, 0);
}
printf(") ");
return TRUE;
default:
/* Not a special function */
return FALSE;
}
}
/* Generate code for all event flag functions */
gen_ef_func(stmt_type, ep, sp, fname, func_code)
int stmt_type; /* ACTION_STMT or EVENT_STMT */
Expr *ep; /* ptr to function in the expression */
Expr *sp; /* current State struct */
char *fname; /* function name */
enum fcode func_code;
{
Expr *ep1, *ep2, *ep3;
Var *vp;
Chan *cp;
ep1 = ep->left; /* ptr to 1-st parameters */
if (ep1 != 0 && ep1->type == E_COMMA)
ep1 = ep1->left;
if ( (ep1 != 0) && (ep1->type == E_VAR) )
vp = (Var *)findVar(ep1->value);
else
vp = 0;
if (vp == 0 || vp->type != V_EVFLAG)
{
fprintf(stderr, "Line %d: ", ep->line_num);
fprintf(stderr,
"Parameter to \"%s\" must be an event flag\n", fname);
}
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("seq_%s(ssId, %s)", fname, vp->name);
}
return;
}
/* Generate code for pv functions requiring a database variable.
* The channel id (index into channel array) is substituted for the variable
*/
gen_pv_func(stmt_type, ep, sp, fname)
int stmt_type; /* ACTION_STMT or EVENT_STMT */
Expr *ep; /* ptr to function in the expression */
Expr *sp; /* current State struct */
char *fname; /* function name */
{
Expr *ep1, *ep2, *ep3;
Var *vp;
Chan *cp;
int index;
ep1 = ep->left; /* ptr to 1-st parameter in the function */
if (ep1 != 0 && ep1->type == E_COMMA)
ep1 = ep1->left;
if (ep1 == 0)
{
fprintf(stderr, "Line %d: ", ep->line_num);
fprintf(stderr,
"Function \"%s\" requires a parameter.\n", fname);
return;
}
vp = 0;
if (ep1->type == E_VAR)
{
vp = (Var *)findVar(ep1->value);
}
else if (ep1->type == E_SUBSCR)
{ /* Form should be: <db variable>[<expression>] */
ep2 = ep1->left; /* variable */
ep3 = ep1->right; /* subscript */
if ( ep2->type == E_VAR )
{
vp = (Var *)findVar(ep2->value);
}
}
if (vp == 0)
{
fprintf(stderr, "Line %d: ", ep->line_num);
fprintf(stderr,
"Parameter to \"%s\" is not a defined variable.\n", fname);
cp=0;
}
else
{
#ifdef DEBUG
fprintf(stderr, "gen_pv_func: var=%s\n", ep1->value);
#endif /*DEBUG*/
cp = vp->chan;
index = cp->index;
}
if ( (vp != 0) && (cp == 0) )
{
fprintf(stderr, "Line %d: ", ep->line_num);
fprintf(stderr,
"Parameter to \"%s\" must be DB variable.\n", fname);
index=-1;
}
printf("seq_%s(ssId, %d", fname, index);
if (ep1->type == E_SUBSCR) /* subscripted variable? */
{ /* e.g. pvPut(xyz[i+2]); => seq_pvPut(ssId, 3 + (i+2)); */
printf(" + (");
/* evalute the subscript expression */
eval_expr(stmt_type, ep3, sp, 0);
printf(")");
}
/* Add any additional parameter(s) */
ep1 = ep1->next;
while (ep1 != 0)
{
printf(", ");
eval_expr(stmt_type, ep1, sp, 0);
ep1 = ep1->next;
}
/* Close the parameter list */
printf(") \n");
return;
}
/* Generate exit handler code */
gen_exit_handler()
{
extern Expr *exit_code_list;
Expr *ep;
printf("/* Exit handler */\n");
printf("static void exit_handler(ssId, pVar)\n");
printf("int\tssId;\n");
printf("struct UserVar\t*pVar;\n{\n");
for (ep = exit_code_list; ep != 0; ep = ep->next)
{
eval_expr(EXIT_STMT, ep, 0, 1);
}
printf("}\n\n");
}
-546
View File
@@ -1,546 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
gen_tables.c,v 1.2 1995/06/27 15:25:45 wright Exp
DESCRIPTION: Generate tables for run-time sequencer.
See also: phase2.c & gen_ss_code.c
ENVIRONMENT: UNIX
HISTORY:
28apr92,ajk Implemented new event flag mode.
01mar94,ajk Implemented new interface to sequencer (see seqCom.h).
01mar94,ajk Implemented assignment of array elements to db channels.
17may94,ajk removed old event flag (-e) option.
20jul95,ajk Added unsigned types.
22jul96,ajk Added castS to action, event, delay, and exit functions.
09mar98,wfl Avoided compilation warnings under Tornado
11mar98,wfl Corrected calculation of number of event words.
***************************************************************************/
/*#define DEBUG 1*/
#include <stdio.h>
#include "parse.h"
#include <dbDefs.h>
#include <seqCom.h>
/*+************************************************************************
* NAME: gen_tables
*
* CALLING SEQUENCE
* type argument I/O description
* ---------------------------------------------------
*
* RETURNS: n/a
*
* FUNCTION: Generate C code from tables.
*
* NOTES: All inputs are external globals.
*-*************************************************************************/
gen_tables()
{
extern Expr *ss_list; /* state sets (from parse) */
extern char *global_c_code; /* global C code */
printf("\f/************************ Tables ***********************/\n");
/* Generate DB blocks */
gen_db_blocks();
/* Generate State Blocks */
gen_state_blocks();
/* Generate State Set Blocks */
gen_ss_array();
/* generate program parameter string */
gen_prog_params();
/* Generate state program table */
gen_prog_table();
return;
}
/* Generate database blocks with structure and data for each defined channel */
gen_db_blocks()
{
extern Chan *chan_list;
Chan *cp;
int nchan, elem_num;
printf("\n/* Database Blocks */\n");
printf("static struct seqChan seqChan[NUM_CHANNELS] = {\n");
nchan = 0;
for (cp = chan_list; cp != NULL; cp = cp->next)
{
#ifdef DEBUG
fprintf(stderr, "gen_db_blocks: index=%d, num_elem=%d\n",
cp->index, cp->num_elem);
#endif /*DEBUG*/
if (cp->num_elem == 0)
{ /* Variable assigned to single pv */
fill_db_block(cp, 0);
nchan++;
}
else
{ /* Variable assigned to multiple pv's */
for (elem_num = 0; elem_num < cp->num_elem; elem_num++)
{
fill_db_block(cp, elem_num);
nchan++;
}
}
}
printf("};\n");
return;
}
/* Fill in a db block with data (all elements for "seqChan" struct) */
fill_db_block(cp, elem_num)
Chan *cp;
int elem_num;
{
Var *vp;
char *type_string, *suffix, elem_str[20], *db_name;
extern char *prog_name;
extern int reent_opt;
extern int num_events;
int size, count, ef_num, mon_flag;
char *db_type_str();
vp = cp->var;
/* Figure out text needed to handle subscripts */
if (vp->class == VC_ARRAY1 || vp->class == VC_ARRAYP)
sprintf(elem_str, "[%d]", elem_num);
else if (vp->class == VC_ARRAY2)
sprintf(elem_str, "[%d][0]", elem_num);
else
sprintf(elem_str, "");
if (vp->type == V_STRING)
suffix = "[0]";
else
suffix = "";
/* Pick up other db info */
if (cp->num_elem == 0)
{
db_name = cp->db_name;
mon_flag = cp->mon_flag;
ef_num = cp->ef_num;
}
else
{
db_name = cp->db_name_list[elem_num];
mon_flag = cp->mon_flag_list[elem_num];
ef_num = cp->ef_num_list[elem_num];
}
if (db_name == NULL)
db_name = ""; /* not assigned */
/* Now, fill in the dbCom structure */
printf(" {\"%s\", ", db_name);/* unexpanded db channel name */
/* Ptr or offset to user variable */
printf("(void *)");
if (reent_opt)
printf("OFFSET(struct UserVar, %s%s%s), ", vp->name, elem_str, suffix);
else
printf("&%s%s%s, ", vp->name, elem_str, suffix); /* variable ptr */
/* variable name with optional elem num */
printf("\"%s%s\", ", vp->name, elem_str);
/* variable type */
printf("\n \"%s\", ", db_type_str(vp->type) );
/* count for db requests */
printf("%d, ", cp->count);
/* event number */
printf("%d, ", cp->index + elem_num + num_events + 1);
/* event flag number (or 0) */
printf("%d, ", ef_num);
/* monitor flag */
printf("%d", mon_flag);
printf("},\n\n");
return;
}
/* Convert variable type to db type as a string */
char *db_type_str(type)
int type;
{
switch (type)
{
case V_CHAR: return "char";
case V_SHORT: return "short";
case V_INT: return "int";
case V_LONG: return "long";
case V_UCHAR: return "unsigned char";
case V_USHORT:return "unsigned short";
case V_UINT: return "unsigned int";
case V_ULONG: return "unsigned long";
case V_FLOAT: return "float";
case V_DOUBLE: return "double";
case V_STRING: return "string";
default: return "";
}
}
/* Generate structure and data for state blocks */
gen_state_blocks()
{
extern Expr *ss_list;
Expr *ssp;
Expr *sp;
int nstates, n;
extern int num_events, num_channels;
int numEventWords;
bitMask *pEventMask;
/* Allocate an array for event mask bits (NB, bit zero is not used) */
numEventWords = (num_events + num_channels + NBITS)/NBITS;
pEventMask = (bitMask *)calloc(numEventWords, sizeof (bitMask));
/* for all state sets ... */
for (ssp = ss_list; ssp != NULL; ssp = ssp->next)
{
/* Build event mask arrays for each state */
printf("\n/* Event masks for state set %s */\n", ssp->value);
for (sp = ssp->left; sp != NULL; sp = sp->next)
{
eval_state_event_mask(sp, pEventMask, numEventWords);
printf("\t/* Event mask for state %s: */\n", sp->value);
printf("static bitMask\tEM_%s_%s[] = {\n", ssp->value, sp->value);
for (n = 0; n < numEventWords; n++)
printf("\t0x%08x,\n", pEventMask[n]);
printf("};\n");
}
/* Build state block for each state in this state set */
printf("\n/* State Blocks */\n");
printf("\nstatic struct seqState state_%s[] = {\n", ssp->value);
nstates = 0;
for (sp = ssp->left; sp != NULL; sp = sp->next)
{
nstates++;
fill_state_block(sp, ssp->value);
}
printf("\n};\n");
}
free(pEventMask);
return;
}
/* Fill in data for a state block (see seqState in seqCom.h) */
fill_state_block(sp, ss_name)
Expr *sp;
char *ss_name;
{
printf("\t/* State \"%s\" */ {\n", sp->value);
printf("\t/* state name */ \"%s\",\n", sp->value);
printf("\t/* action function */ (ACTION_FUNC) A_%s_%s,\n", ss_name, sp->value);
printf("\t/* event function */ (EVENT_FUNC) E_%s_%s,\n", ss_name, sp->value);
printf("\t/* delay function */ (DELAY_FUNC) D_%s_%s,\n", ss_name, sp->value);
printf("\t/* event mask array */ EM_%s_%s},\n\n", ss_name, sp->value);
return;
}
/* Generate the program parameter list */
gen_prog_params()
{
extern char *prog_param;
printf("\n/* Program parameter list */\n");
printf("static char prog_param[] = \"%s\";\n", prog_param);
}
/* Generate the structure with data for a state program table (SPROG) */
gen_prog_table()
{
extern int reent_opt;
extern char *prog_name;
extern Expr exit_code_list;
int i;
printf("\n/* State Program table (global) */\n");
printf("struct seqProgram %s = {\n", prog_name);
printf("\t/* magic number */ %d,\n", MAGIC); /* magic number */
printf("\t/* *name */ \"%s\",\n", prog_name);/* program name */
printf("\t/* *pChannels */ seqChan,\n"); /* table of db channels */
printf("\t/* numChans */ NUM_CHANNELS,\n"); /* number of db channels */
printf("\t/* *pSS */ seqSS,\n"); /* array of SS blocks */
printf("\t/* numSS */ NUM_SS,\n"); /* number of state sets */
if (reent_opt)
printf("\t/* user variable size */ sizeof(struct UserVar),\n");
else
printf("\t/* user variable size */ 0,\n");
printf("\t/* *pParams */ prog_param,\n"); /* program parameters */
printf("\t/* numEvents */ NUM_EVENTS,\n"); /* number event flags */
printf("\t/* encoded options */ ");
encode_options();
printf("\t/* exit handler */ (EXIT_FUNC) exit_handler,\n");
printf("};\n");
return;
}
encode_options()
{
extern int async_opt, debug_opt, reent_opt,
newef_opt, conn_opt, vx_opt;
printf("(0");
if (async_opt)
printf(" | OPT_ASYNC");
if (conn_opt)
printf(" | OPT_CONN");
if (debug_opt)
printf(" | OPT_DEBUG");
if (newef_opt)
printf(" | OPT_NEWEF");
if (reent_opt)
printf(" | OPT_REENT");
if (vx_opt)
printf(" | OPT_VXWORKS");
printf("),\n");
return;
}
/* Generate an array of state set blocks, one entry for each state set */
gen_ss_array()
{
extern Expr *ss_list;
Expr *ssp;
int nss, nstates, n;
printf("\n/* State Set Blocks */\n");
printf("static struct seqSS seqSS[NUM_SS] = {\n");
nss = 0;
for (ssp = ss_list; ssp != NULL; ssp = ssp->next)
{
if (nss > 0)
printf("\n\n");
nss++;
printf("\t/* State set \"%s\" */ {\n", ssp->value);
printf("\t/* ss name */ \"%s\",\n", ssp->value);
printf("\t/* ptr to state block */ state_%s,\n", ssp->value);
nstates = exprCount(ssp->left);
printf("\t/* number of states */ %d,\n", nstates, ssp->value);
printf("\t/* error state */ %d},\n", find_error_state(ssp));
}
printf("};\n");
return;
}
/* Find the state named "error" in a state set */
find_error_state(ssp)
Expr *ssp;
{
Expr *sp;
int error_state;
for (sp = ssp->left, error_state = 0; sp != 0; sp = sp->next, error_state++)
{
if (strcmp(sp->value, "error") == 0)
return error_state;
}
return -1; /* no state named "error" in this state set */
}
/* Evaluate composite event mask for a single state */
eval_state_event_mask(sp, pEventWords, numEventWords)
Expr *sp;
bitMask *pEventWords;
int numEventWords;
{
int n;
int eval_event_mask(), eval_event_mask_subscr();
Expr *tp;
/* Set appropriate bits based on transition expressions.
* Here we look at the when() statement for references to event flags
* and database variables. Database variables might have a subscript,
* which could be a constant (set a single event bit) or an expression
* (set a group of bits for the possible range of the evaluated expression)
*/
for (n = 0; n < numEventWords; n++)
pEventWords[n] = 0;
for (tp = sp->left; tp != 0; tp = tp->next)
{
/* look for simple variables, e.g. "when(x > 0)" */
traverseExprTree(tp->left, E_VAR, 0, eval_event_mask, pEventWords);
/* look for subscripted variables, e.g. "when(x[i] > 0)" */
traverseExprTree(tp->left, E_SUBSCR, 0, eval_event_mask_subscr, pEventWords);
}
#ifdef DEBUG
fprintf(stderr, "Event mask for state %s is", sp->value);
for (n = 0; n < numEventWords; n++)
fprintf(stderr, " 0x%x", pEventWords[n]);
fprintf(stderr, "\n");
#endif /*DEBUG*/
}
/* Evaluate the event mask for a given transition (when() statement).
* Called from traverseExprTree() when ep->type==E_VAR.
*/
eval_event_mask(ep, pEventWords)
Expr *ep;
bitMask *pEventWords;
{
Chan *cp;
Var *vp;
extern int num_events;
vp = (Var *)ep->left;
if (vp == 0)
return; /* this shouldn't happen */
/* event flag? */
if (vp->type == V_EVFLAG)
{
#ifdef DEBUG
fprintf(stderr, " eval_event_mask: %s, ef_num=%d\n",
vp->name, vp->ef_num);
#endif /*DEBUG*/
bitSet(pEventWords, vp->ef_num);
return;
}
/* database channel? */
cp = vp->chan;
if (cp != NULL && cp->num_elem == 0)
{
#ifdef DEBUG
fprintf(stderr, " eval_event_mask: %s, db event bit=%d\n",
vp->name, cp->index + 1);
#endif /*DEBUG*/
bitSet(pEventWords, cp->index + num_events + 1);
}
return;
}
/* Evaluate the event mask for a given transition (when() statement)
* for subscripted database variables.
* Called from traverseExprTree() when ep->type==E_SUBSCR.
*/
eval_event_mask_subscr(ep, pEventWords)
Expr *ep;
bitMask *pEventWords;
{
extern int num_events;
Chan *cp;
Var *vp;
Expr *ep1, *ep2;
int subscr, n;
ep1 = ep->left;
if (ep1 == 0 || ep1->type != E_VAR)
return;
vp = (Var *)ep1->left;
if (vp == 0)
return; /* this shouldn't happen */
cp = vp->chan;
if (cp == NULL)
return;
/* Only do this if the array is assigned to multiple pv's */
if (cp->num_elem == 0)
{
#ifdef DEBUG
fprintf(stderr, " eval_event_mask_subscr: %s, db event bit=%d\n",
vp->name, cp->index);
#endif /*DEBUG*/
bitSet(pEventWords, cp->index + num_events + 1);
return;
}
/* Is this subscript a constant? */
ep2 = ep->right;
if (ep2 == 0)
return;
if (ep2->type == E_CONST)
{
subscr = atoi(ep2->value);
if (subscr < 0 || subscr >= cp->num_elem)
return;
#ifdef DEBUG
fprintf(stderr, " eval_event_mask_subscr: %s, db event bit=%d\n",
vp->name, cp->index + subscr + 1);
#endif /*DEBUG*/
bitSet(pEventWords, cp->index + subscr + num_events + 1);
return;
}
/* subscript is an expression -- set all event bits for this variable */
#ifdef DEBUG
fprintf(stderr, " eval_event_mask_subscr: %s, db event bits=%d..%d\n",
vp->name, cp->index + 1, cp->index + vp->length1);
#endif /*DEBUG*/
for (n = 0; n < vp->length1; n++)
{
bitSet(pEventWords, cp->index + n + num_events + 1);
}
return;
}
/* Count the number of linked expressions */
exprCount(ep)
Expr *ep;
{
int count;
for (count = 0; ep != 0; ep = ep->next)
count++;
return count;
}
-10
View File
@@ -1,10 +0,0 @@
#!/bin/sh
#
# makeSeqVersion - create the sequencer version module
#
VERSION=`cat $1`
DATE=`date`
echo '/* seqVersion.c - version & date */'
echo '/* Created by makeVersion */'
echo 'char *seqVersion = "@(#)SEQ Version '${VERSION}': '${DATE}'";'
-10
View File
@@ -1,10 +0,0 @@
#!/bin/sh
#
# makeVersion - create the snc version module
#
VERSION=`cat $1`
DATE=`date`
echo '/* sncVersion.c - version & date */'
echo '/* Created by makeVersion */'
echo 'char *sncVersion = "@(#)SNC Version '${VERSION}': '${DATE}'";'
-22
View File
@@ -1,22 +0,0 @@
#!/usr/bin/perl
#
# makeVersion - create the snc version module
#
# Usage: perl makeVersion.pl {Version_file} {Symbol Name}
$version_file = $ARGV[0];
$symbol = $ARGV[1];
$out = "$symbol.c";
open IN, $version_file or die "Cannot open $version_file";
$version=<IN>;
chomp $version;
close IN;
$date = localtime();
open OUT, ">$out" or die "Cannot create $out";
print OUT "/* $out - version & date */\n";
print OUT "/* Created by makeVersion.pl */\n";
print OUT "char *$symbol = \"\@(#)SNC/SEQ Version $version : $date\";\n";
close OUT;
-726
View File
@@ -1,726 +0,0 @@
/*#define DEBUG 1*/
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
< parse.c,v 1.3 1995/10/19 16:30:16 wright Exp
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
HISTORY:
19nov91,ajk Replaced lstLib calls with built-in links.
20nov91,ajk Removed snc_init() - no longer did anything useful.
20nov91,ajk Added option_stmt() routine.
28apr92,ajk Implemented new event flag mode.
29opc93,ajk Implemented assignment of pv's to array elements.
29oct93,ajk Implemented variable class (VC_SIMPLE, VC_ARRAY, & VC_POINTER).
29oct93,ajk Added 'v' (vxWorks include) option.
17may94,ajk Removed old event flag (-e) option.
***************************************************************************/
/*====================== Includes, globals, & defines ====================*/
#include <ctype.h>
#include <stdio.h>
#include "parse.h" /* defines linked list structures */
#include <math.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif /*TRUE*/
int debug_print_opt = 0; /* Debug level (set by source file) */
char *prog_name; /* ptr to program name (string) */
char *prog_param; /* parameter string for program stmt */
Expr *defn_c_list; /* definition C code list */
Expr *ss_list; /* Start of state set list */
Expr *exit_code_list; /* Start of exit code list */
Var *var_list = NULL; /* start of variable list */
Var *var_tail = NULL; /* tail of variable list */
Chan *chan_list = NULL; /* start of DB channel list */
Chan *chan_tail = NULL; /* tail of DB channel list */
Expr *global_c_list; /* global C code following state program */
/*+************************************************************************
* 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;
{
prog_name = pname;
prog_param = pparam;
#ifdef DEBUG
fprintf(stderr, "program name = %s\n", prog_name);
#endif
return;
}
/* Parsing a declaration statement */
decl_stmt(type, class, name, s_length1, s_length2, value)
int type; /* variable type (e.g. V_FLOAT) */
int class; /* variable class (e.g. VC_ARRAY) */
char *name; /* ptr to variable name */
char *s_length1; /* array lth (1st dim, arrays only) */
char *s_length2; /* array lth (2nd dim, [n]x[m] arrays only) */
char *value; /* initial value or NULL */
{
Var *vp;
int length1, length2;
extern int line_num;
#ifdef DEBUG
fprintf(stderr,
"variable decl: type=%d, class=%d, name=%s, ", type, class, name);
#endif
length1 = length2 = 1;
if (s_length1 != NULL)
{
length1 = atoi(s_length1);
if (length1 <= 0)
length1 = 1;
}
if (s_length2 != NULL)
{
length2 = atoi(s_length2);
if (length2 <= 0)
length2 = 1;
}
#ifdef DEBUG
fprintf(stderr, "length1=%d, length2=%d\n", length1, length2);
#endif
/* See if variable already declared */
vp = (Var *)findVar(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();
addVar(vp); /* add to var list */
vp->name = name;
vp->class = class;
vp->type = type;
vp->length1 = length1;
vp->length2 = length2;
vp->value = value; /* initial value or NULL */
vp->chan = NULL;
return;
}
/* Option statement */
option_stmt(option, value)
char *option; /* "a", "r", ... */
int value; /* TRUE means +, FALSE means - */
{
extern int async_opt, conn_opt, debug_opt, line_opt,
reent_opt, warn_opt, vx_opt, newef_opt;
switch(*option)
{
case 'a':
async_opt = value;
break;
case 'c':
conn_opt = value;
break;
case 'd':
debug_opt = value;
break;
case 'e':
newef_opt = value;
break;
case 'l':
line_opt = value;
break;
case 'r':
reent_opt = value;
break;
case 'w':
warn_opt = value;
break;
case 'v':
vx_opt = value;
break;
}
return;
}
/* "Assign" statement: Assign a variable to a DB channel.
* Format: assign <variable> to <string;
* Note: Variable may be subscripted.
*/
assign_single(name, db_name)
char *name; /* ptr to variable name */
char *db_name; /* ptr to db name */
{
Chan *cp;
Var *vp;
int subNum;
extern int line_num;
#ifdef DEBUG
fprintf(stderr, "assign %s to \"%s\";\n", name, db_name);
#endif /*DEBUG*/
/* Find the variable */
vp = (Var *)findVar(name);
if (vp == 0)
{
fprintf(stderr, "assign: variable %s not declared, line %d\n",
name, line_num);
return;
}
cp = vp->chan;
if (cp != NULL)
{
fprintf(stderr, "assign: %s already assigned, line %d\n",
name, line_num);
return;
}
/* Build structure for this channel */
cp = (Chan *)build_db_struct(vp);
cp->db_name = db_name; /* DB name */
/* The entire variable is assigned */
cp->count = vp->length1 * vp->length2;
return;
}
/* "Assign" statement: assign an array element to a DB channel.
* Format: assign <variable>[<subscr>] to <string>; */
assign_subscr(name, subscript, db_name)
char *name; /* ptr to variable name */
char *subscript; /* subscript value or NULL */
char *db_name; /* ptr to db name */
{
Chan *cp;
Var *vp;
int subNum;
extern int line_num;
#ifdef DEBUG
fprintf(stderr, "assign %s[%s] to \"%s\";\n", name, subscript, db_name);
#endif /*DEBUG*/
/* Find the variable */
vp = (Var *)findVar(name);
if (vp == 0)
{
fprintf(stderr, "assign: variable %s not declared, line %d\n",
name, line_num);
return;
}
if (vp->class != VC_ARRAY1 && vp->class != VC_ARRAY2)
{
fprintf(stderr, "assign: variable %s not an array, line %d\n",
name, line_num);
return;
}
cp = vp->chan;
if (cp == NULL)
{
/* Build structure for this channel */
cp = (Chan *)build_db_struct(vp);
}
else if (cp->db_name != NULL)
{
fprintf(stderr, "assign: array %s already assigned, line %d\n",
name, line_num);
return;
}
subNum = atoi(subscript);
if (subNum < 0 || subNum >= vp->length1)
{
fprintf(stderr,
"assign: subscript %s[%d] is out of range, line %d\n",
name, subNum, line_num);
return;
}
if (cp->db_name_list == NULL)
alloc_db_lists(cp, vp->length1); /* allocate lists */
else if (cp->db_name_list[subNum] != NULL)
{
fprintf(stderr, "assign: %s[%d] already assigned, line %d\n",
name, subNum, line_num);
return;
}
cp->db_name_list[subNum] = db_name;
cp->count = vp->length2; /* could be a 2-dimensioned array */
return;
}
/* Assign statement: assign an array to multiple DB channels.
* Format: assign <variable> to { <string>, <string>, ... };
* Assignments for double dimensioned arrays:
* <var>[0][0] assigned to 1st db name,
* <var>[1][0] assigned to 2nd db name, etc.
* If db name list contains fewer names than the array dimension,
* the remaining elements receive NULL assignments.
*/
assign_list(name, db_name_list)
char *name; /* ptr to variable name */
Expr *db_name_list; /* ptr to db name list */
{
Chan *cp;
Var *vp;
int elem_num;
extern int line_num;
#ifdef DEBUG
fprintf(stderr, "assign %s to {", name);
#endif /*DEBUG*/
/* Find the variable */
vp = (Var *)findVar(name);
if (vp == 0)
{
fprintf(stderr, "assign: variable %s not declared, line %d\n",
name, line_num);
return;
}
if (vp->class != VC_ARRAY1 && vp->class != VC_ARRAY2)
{
fprintf(stderr, "assign: variable %s is not an array, line %d\n",
name, line_num);
return;
}
cp = vp->chan;
if (cp != NULL)
{
fprintf(stderr, "assign: variable %s already assigned, line %d\n",
name, line_num);
return;
}
/* Build a db structure for this variable */
cp = (Chan *)build_db_struct(vp);
/* Allocate lists */
alloc_db_lists(cp, vp->length1); /* allocate lists */
/* fill in the array of pv names */
for (elem_num = 0; elem_num < vp->length1; elem_num++)
{
if (db_name_list == NULL)
break; /* end of list */
#ifdef DEBUG
fprintf(stderr, "\"%s\", ", db_name_list->value);
#endif /*DEBUG*/
cp->db_name_list[elem_num] = db_name_list->value; /* DB name */
cp->count = vp->length2;
db_name_list = db_name_list->next;
}
#ifdef DEBUG
fprintf(stderr, "};\n");
#endif /*DEBUG*/
return;
}
/* Build a db structure for this variable */
build_db_struct(vp)
Var *vp;
{
Chan *cp;
cp = allocChan();
addChan(cp); /* add to Chan list */
/* make connections between Var & Chan structures */
cp->var = vp;
vp->chan = cp;
/* Initialize the structure */
cp->db_name_list = 0;
cp->mon_flag_list = 0;
cp->ef_var_list = 0;
cp->ef_num_list = 0;
cp->num_elem = 0;
cp->mon_flag = 0;
cp->ef_var = 0;
cp->ef_num = 0;
return (int)cp;
}
/* Allocate lists for assigning multiple pv's to a variable */
alloc_db_lists(cp, length)
Chan *cp;
int length;
{
/* allocate an array of pv names */
cp->db_name_list = (char **)calloc(sizeof(char **), length);
/* allocate an array for monitor flags */
cp->mon_flag_list = (int *)calloc(sizeof(int **), length);
/* allocate an array for event flag var ptrs */
cp->ef_var_list = (Var **)calloc(sizeof(Var **), length);
/* allocate an array for event flag numbers */
cp->ef_num_list = (int *)calloc(sizeof(int **), length);
cp->num_elem = length;
}
/* Parsing a "monitor" statement.
* Format:
* monitor <var>; - monitor a single variable or all elements in an array.
* monitor <var>[<m>]; - monitor m-th element of an array.
*/
monitor_stmt(name, subscript)
char *name; /* variable name (should be assigned) */
char *subscript; /* element number or NULL */
{
Var *vp;
Chan *cp;
int subNum;
extern int line_num;
#ifdef DEBUG
fprintf(stderr, "monitor_stmt: name=%s[%s]\n", name, subscript);
#endif /*DEBUG*/
/* Find the variable */
vp = (Var *)findVar(name);
if (vp == 0)
{
fprintf(stderr, "assign: variable %s not declared, line %d\n",
name, line_num);
return;
}
/* Find a channel assigned to this variable */
cp = vp->chan;
if (cp == 0)
{
fprintf(stderr, "monitor: variable %s not assigned, line %d\n",
name, line_num);
return;
}
if (subscript == NULL)
{
if (cp->num_elem == 0)
{ /* monitor one channel for this variable */
cp->mon_flag = TRUE;
return;
}
/* else monitor all channels in db list */
for (subNum = 0; subNum < cp->num_elem; subNum++)
{ /* 1 pv per element of the array */
cp->mon_flag_list[subNum] = TRUE;
}
return;
}
/* subscript != NULL */
subNum = atoi(subscript);
if (subNum < 0 || subNum >= cp->num_elem)
{
fprintf(stderr, "monitor: subscript of %s out of range, line %d\n",
name, line_num);
return;
}
if (cp->num_elem == 0 || cp->db_name_list[subNum] == NULL)
{
fprintf(stderr, "monitor: %s[%d] not assigned, line %d\n",
name, subNum, line_num);
return;
}
cp->mon_flag_list[subNum] = TRUE;
return;
}
/* Parsing "sync" statement */
sync_stmt(name, subscript, ef_name)
char *name;
char *subscript;
char *ef_name;
{
Chan *cp;
Var *vp;
extern int line_num;
int subNum;
#ifdef DEBUG
fprintf(stderr, "sync_stmt: name=%s, subNum=%s, ef_name=%s\n",
name, subscript, ef_name);
#endif /*DEBUG*/
vp = (Var *)findVar(name);
if (vp == 0)
{
fprintf(stderr, "sync: variable %s not declared, line %d\n",
name, line_num);
return;
}
cp = vp->chan;
if (cp == 0)
{
fprintf(stderr, "sync: variable %s not assigned, line %d\n",
name, line_num);
return;
}
/* Find the event flag varible */
vp = (Var *)findVar(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;
}
if (subscript == NULL)
{ /* no subscript */
if (cp->db_name != NULL)
{ /* 1 pv assigned to this variable */
cp->ef_var = vp;
return;
}
/* 1 pv per element in the array */
for (subNum = 0; subNum < cp->num_elem; subNum++)
{
cp->ef_var_list[subNum] = vp;
}
return;
}
/* subscript != NULL */
subNum = atoi(subscript);
if (subNum < 0 || subNum >= cp->num_elem)
{
fprintf(stderr,
"sync: subscript %s[%d] out of range, line %d\n",
name, subNum, line_num);
return;
}
cp->ef_var_list[subNum] = vp; /* sync to a specific element of the array */
return;
}
/* Definition C code */
defn_c_stmt(c_list)
Expr *c_list; /* ptr to C code */
{
#ifdef DEBUG
fprintf(stderr, "defn_c_stmt\n");
#endif
if (defn_c_list == 0)
defn_c_list = c_list;
else
link_expr(defn_c_list, c_list);
return;
}
/* Global C code (follows state program) */
global_c_stmt(c_list)
Expr *c_list; /* ptr to C code */
{
global_c_list = c_list;
return;
}
/* Add a variable to the variable linked list */
addVar(vp)
Var *vp;
{
if (var_list == NULL)
var_list = vp;
else
var_tail->next = vp;
var_tail = vp;
vp->next = NULL;
}
/* Find a variable by name; returns a pointer to the Var struct;
returns 0 if the variable is not found. */
Var *findVar(name)
char *name;
{
Var *vp;
for (vp = var_list; vp != NULL; vp = vp->next)
{
if (strcmp(vp->name, name) == 0)
{
return vp;
}
}
return 0;
}
/* Add a channel to the channel linked list */
addChan(cp)
Chan *cp;
{
if (chan_list == NULL)
chan_list = cp;
else
chan_tail->next = cp;
chan_tail = cp;
cp->next = NULL;
}
/* Set debug print opt */
set_debug_print(opt)
char *opt;
{
debug_print_opt = atoi(opt);
}
/* Parsing "program" statement */
program(prog_list)
Expr *prog_list;
{
ss_list = prog_list;
#ifdef DEBUG
fprintf(stderr, "----Phase2---\n");
#endif /*DEBUG*/
phase2(ss_list);
exit(0);
}
/* Exit code */
exit_code(ep)
Expr *ep;
{
exit_code_list = ep;
return 0;
}
/* Build an expression list (hierarchical):
Builds a node on a binary tree for each expression primitive.
*/
Expr *expression(type, value, left, right)
int type; /* E_BINOP, E_ASGNOP, etc */
char *value; /* "==", "+=", var name, contstant, etc. */
Expr *left; /* LH side */
Expr *right; /* RH side */
{
Expr *ep;
extern int line_num, c_line_num;
extern char *src_file;
#ifdef DEBUG
extern char *stype[];
#endif
/* Allocate a structure for this item or expression */
ep = allocExpr();
#ifdef DEBUG
fprintf(stderr,
"expression: ep=%d, type=%s, value=\"%s\", left=%d, right=%d\n",
ep, stype[type], value, left, right);
#endif
/* Fill in the structure */
ep->next = (Expr *)0;
ep->last = ep;
ep->type = type;
ep->value = value;
ep->left = left;
ep->right = right;
if (type == E_TEXT)
ep->line_num = c_line_num;
else
ep->line_num = line_num;
ep->src_file = src_file;
return ep;
}
/* Link two expression structures and/or lists. Returns ptr to combined list.
Note: ->last ptrs are correct only for 1-st and last structures in the list */
Expr *link_expr(ep1, ep2)
Expr *ep1; /* beginning of 1-st structure or list */
Expr *ep2; /* beginning 2-nd (append it to 1-st) */
{
Expr *ep;
if (ep1 == 0)
return ep2; /* shouldn't happen */
else if (ep2 == 0)
return ep1;
(ep1->last)->next = ep2;
ep1->last = ep2->last;
#ifdef DEBUG
fprintf(stderr, "link_expr(");
for (ep = ep1; ; ep = ep->next)
{
fprintf(stderr, "%d, ", ep);
if (ep == ep1->last)
break;
}
fprintf(stderr, ")\n");
#endif /*DEBUG*/
return ep1;
}
/* Interpret pre-processor code */
pp_code(line, fname)
char *line;
char *fname;
{
extern int line_num;
extern char *src_file;
line_num = atoi(line);
src_file = fname;
}
/* The ordering of this list must correspond with the ordering in parse.h */
char *stype[] = {
"E_EMPTY", "E_CONST", "E_VAR", "E_FUNC", "E_STRING", "E_UNOP", "E_BINOP",
"E_ASGNOP", "E_PAREN", "E_SUBSCR", "E_TEXT", "E_STMT", "E_CMPND",
"E_IF", "E_ELSE", "E_WHILE", "E_SS", "E_STATE", "E_WHEN",
"E_FOR", "E_X", "E_PRE", "E_POST", "E_BREAK", "E_COMMA",
"E_?", "E_?", "E_?", "E_?", "E_?", "E_?", "E_?", "E_?", "E_?" };
-125
View File
@@ -1,125 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1989-93, The Regents of the University of California.
Los Alamos National Laboratory
parse.h,v 1.2 1995/06/27 15:25:50 wright Exp
DESCRIPTION: Structures for parsing the state notation language.
ENVIRONMENT: UNIX
HISTORY:
18nov91,ajk Replaced lstLib stuff with in-line links.
28oct93,ajk Added support for assigning array elements to pv's.
28oct93,ajk Added support for pointer declarations (see VC_*)
5nov93,ajk Changed structures var & db_chan to handle array assignments.
5nov93,ajk changed malloc() to calloc() 3 places.
***************************************************************************/
/* 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.
*/
struct expression /* Expression block */
{
struct expression *next; /* link to next expression */
struct expression *last; /* link to last in list */
struct expression *left; /* ptr to left expression */
struct expression *right; /* ptr to right expression */
int type; /* expression type (E_*) */
char *value; /* operator or value string */
int line_num; /* line number */
char *src_file; /* effective source file */
};
typedef struct expression Expr;
struct var /* Variable or function definition */
{
struct var *next; /* link to next item in list */
char *name; /* variable name */
char *value; /* initial value or NULL */
int type; /* var type */
int class; /* simple, array, or pointer */
int length1; /* 1st dim. array lth (default=1) */
int length2; /* 2nd dim. array lth (default=1) */
int ef_num; /* bit number if this is an event flag */
struct db_chan *chan; /* ptr to channel struct if assigned */
};
typedef struct var Var;
struct db_chan /* DB channel assignment info */
{
struct db_chan *next; /* link to next item in list */
char *db_name; /* database name (assign all to 1 pv) */
char **db_name_list; /* list of db names (assign each to a pv) */
int num_elem; /* number of elements assigned in db_name_list */
Var *var; /* ptr to variable definition */
int count; /* count for db access */
int mon_flag; /* TRUE if channel is "monitored" */
int *mon_flag_list; /* ptr to list of monitor flags */
Var *ef_var; /* ptr to event flag variable for sync */
Var **ef_var_list; /* ptr to list of event flag variables */
int ef_num; /* event flag number */
int *ef_num_list; /* list of event flag numbers */
int index; /* index in database channel array (seqChan) */
};
typedef struct db_chan Chan;
/* Note: Only one of db_name or db_name_list can have a non-zero value */
Expr *expression(), *link_expr();
Var *findVar();
Chan *findChan();
/* Linked list allocation definitions */
#define allocExpr() (Expr *)calloc(1, sizeof(Expr));
#define allocVar() (Var *)calloc(1, sizeof(Var));
#define allocChan() (Chan *)calloc(1, sizeof(Chan));
/* Variable types */
#define V_NONE 0 /* not defined */
#define V_CHAR 1 /* char */
#define V_SHORT 2 /* short */
#define V_INT 3 /* int */
#define V_LONG 4 /* long */
#define V_FLOAT 5 /* float */
#define V_DOUBLE 6 /* double */
#define V_STRING 7 /* strings (array of char) */
#define V_EVFLAG 8 /* event flag */
#define V_FUNC 9 /* function (not a variable) */
#define V_UCHAR 11 /* unsigned char */
#define V_USHORT 12 /* unsigned short */
#define V_UINT 13 /* unsigned int */
#define V_ULONG 14 /* unsigned long */
/* Variable classes */
#define VC_SIMPLE 0 /* simple (un-dimentioned) variable */
#define VC_ARRAY1 1 /* single dim. array */
#define VC_ARRAY2 2 /* multiple dim. array */
#define VC_POINTER 3 /* pointer */
#define VC_ARRAYP 4 /* array of pointers */
/* Expression types */
#define E_EMPTY 0 /* empty expression */
#define E_CONST 1 /* numeric constant */
#define E_VAR 2 /* variable */
#define E_FUNC 3 /* function */
#define E_STRING 4 /* ptr to string consatant */
#define E_UNOP 5 /* unary operator: OP expr (-, +, or !) */
#define E_BINOP 6 /* binary operator: expr OP expr */
#define E_ASGNOP 7 /* assign operatro: (=, +=, *=, etc.) */
#define E_PAREN 8 /* parenthesis around an expression */
#define E_SUBSCR 9 /* subscript */
#define E_TEXT 10 /* C code or other text to be inserted */
#define E_STMT 11 /* simple statement */
#define E_CMPND 12 /* begin compound statement: {...} */
#define E_IF 13 /* if statement */
#define E_ELSE 14 /* if statement */
#define E_WHILE 15 /* while statement */
#define E_SS 16 /* state set statement */
#define E_STATE 17 /* state statement */
#define E_WHEN 18 /* when statement */
#define E_FOR 19 /* for statement */
#define E_X 20 /* eXpansion (e.g. for(;;) */
#define E_PRE 21 /* ++expr or --expr */
#define E_POST 22 /* expr++ or expr-- */
#define E_BREAK 23 /* break stmt */
#define E_COMMA 24 /* expr , expr */
-555
View File
@@ -1,555 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
phase2.c,v 1.2 1995/06/27 15:25:52 wright Exp
DESCRIPTION: Phase 2 code generation routines for SNC.
Produces code and tables in C output file.
See also: gen_ss_code.c and gen_tables.c
ENVIRONMENT: UNIX
HISTORY:
19nov91,ajk Replaced lstLib calls with built-in linked list.
19nov91,ajk Removed extraneous "static" from "UserVar" declaration.
01mar94,ajk Implemented new interface to sequencer (seqCom.h).
01mar94,ajk Implemented assignment of array elements to db channels.
01mar94,ajk Changed algorithm for assigning event bits.
13jan98,wfl Supported E_COMMA token (for compound expressions).
09mar98,wfl Avoided compilation warnings under Tornado
01oct98,wfl Supported setting initial value on declaration.
***************************************************************************/
/*#define DEBUG 1*/
#include <stdio.h>
#include "parse.h"
#include <seqCom.h>
int num_channels = 0; /* number of db channels */
int num_events = 0; /* number of event flags */
int num_ss = 0; /* number of state sets */
int max_delays = 0; /* maximum number of delays per state */
int num_errors = 0; /* number of errors detected in phase 2 processing */
/*+************************************************************************
* NAME: phase2
*
* CALLING SEQUENCE
* type argument I/O description
* ---------------------------------------------------
*
* RETURNS: n/a
*
* FUNCTION: Generate C code from parsing lists.
*
* NOTES: All inputs are external globals.
*-*************************************************************************/
phase2()
{
extern Var *var_list; /* variables (from parse) */
extern Expr *ss_list; /* state sets (from parse) */
extern Expr *global_c_list; /* global C code */
/* Count number of db channels and state sets defined */
num_channels = db_chan_count();
num_ss = exprCount(ss_list);
/* Reconcile all variable and tie each to the appropriate VAR struct */
reconcile_variables();
/* reconcile all state names, including next state in transitions */
reconcile_states();
/* Assign bits for event flags */
assign_ef_bits();
/* Assign delay id's */
assign_delay_ids();
/* Generate preamble code */
gen_preamble();
/* Generate variable declarations */
gen_var_decl();
/* Generate definition C code */
gen_defn_c_code();
/* Generate code for each state set */
gen_ss_code();
/* Generate tables */
gen_tables();
/* Output global C code */
gen_global_c_code();
exit(0);
}
/* Generate preamble (includes, defines, etc.) */
gen_preamble()
{
extern char *prog_name;
extern int async_opt, conn_opt, debug_opt, reent_opt;
/* Program name (comment) */
printf("/* Program \"%s\" */\n", prog_name);
/* Include files */
printf("#define ANSI\n"); /* Expands ANSI prototypes in seqCom.h */
printf("#include \"seqCom.h\"\n");
/* Local definitions */
printf("\n#define NUM_SS %d\n", num_ss);
printf("#define NUM_CHANNELS %d\n", num_channels);
printf("#define NUM_EVENTS %d\n", num_events);
/* The following definition should be consistant with db_access.h */
printf("#define MAX_STRING_SIZE 40\n");
/* #define's for compiler options */
gen_opt_defn(async_opt, "ASYNC_OPT");
gen_opt_defn(conn_opt, "CONN_OPT" );
gen_opt_defn(debug_opt, "DEBUG_OPT");
gen_opt_defn(reent_opt, "REENT_OPT");
printf("\n");
/* Forward references of tables: */
printf("\nextern struct seqProgram %s;\n", prog_name);
return;
}
/* Generate defines for compiler options */
gen_opt_defn(opt, defn_name)
int opt;
char *defn_name;
{
if (opt)
printf("#define %s TRUE\n", defn_name);
else
printf("#define %s FALSE\n", defn_name);
}
/* Reconcile all variables in an expression,
* and tie each to the appropriate VAR structure.
*/
int printTree = FALSE; /* For debugging only */
reconcile_variables()
{
extern Expr *ss_list, *exit_code_list;
Expr *ssp, *ep;
int connect_variable();
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
{
#ifdef DEBUG
fprintf(stderr, "reconcile_variables: ss=%s\n", ssp->value);
#endif /*DEBUG*/
traverseExprTree(ssp, E_VAR, 0, connect_variable, 0);
}
/* Same for exit procedure */
for (ep = exit_code_list; ep != 0; ep = ep->next)
{
traverseExprTree(ep, E_VAR, 0, connect_variable, 0);
}
}
/* Connect a variable in an expression to the the Var structure */
int connect_variable(ep)
Expr *ep;
{
Var *vp;
extern char *stype[];
extern int warn_opt;
if (ep->type != E_VAR)
return;
#ifdef DEBUG
fprintf(stderr, "connect_variable: \"%s\", line %d\n", ep->value, ep->line_num);
#endif
vp = (Var *)findVar(ep->value);
if (vp == 0)
{ /* variable not declared; add it to the variable list */
if (warn_opt)
fprintf(stderr,
"Warning: variable \"%s\" is used but not declared.\n",
ep->value);
vp = allocVar();
addVar(vp);
vp->name = ep->value;
vp->type = V_NONE; /* undeclared type */
vp->length1 = 1;
vp->length2 = 1;
vp->value = 0;
}
ep->left = (Expr *)vp; /* make connection */
return;
}
/* Reconcile state names */
reconcile_states()
{
extern Expr *ss_list;
extern int num_errors;
Expr *ssp, *sp, *sp1, tr;
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
{
for (sp = ssp->left; sp != 0; sp = sp->next)
{
/* Check for duplicate state names in this state set */
for (sp1 = sp->next; sp1 != 0; sp1 = sp1->next)
{
if (strcmp(sp->value, sp1->value) == 0)
{
fprintf(stderr,
"State \"%s\" is duplicated in state set \"%s\"\n",
sp->value, ssp->value);
num_errors++;
}
}
}
}
}
/* Find a state by name */
Expr *find_state(name, sp)
char *name; /* state name */
Expr *sp; /* beginning of state list */
{
while (sp != 0)
{
if (strcmp(name, sp->value) == 0)
return sp;
sp = sp->next;
}
return 0;
}
/* Generate a C variable declaration for each variable declared in SNL */
gen_var_decl()
{
extern Var *var_list;
Var *vp;
char *vstr;
int nv;
extern int reent_opt;
printf("\n/* Variable declarations */\n");
/* Convert internal type to `C' type */
if (reent_opt)
printf("struct UserVar {\n");
for (nv=0, vp = var_list; vp != NULL; nv++, vp = vp->next)
{
switch (vp->type)
{
case V_CHAR:
vstr = "char";
break;
case V_INT:
vstr = "int";
break;
case V_LONG:
vstr = "long";
break;
case V_SHORT:
vstr = "short";
break;
case V_UCHAR:
vstr = "unsigned char";
break;
case V_UINT:
vstr = "unsigned int";
break;
case V_ULONG:
vstr = "unsigned long";
break;
case V_USHORT:
vstr = "unsigned short";
break;
case V_FLOAT:
vstr = "float";
break;
case V_DOUBLE:
vstr = "double";
break;
case V_STRING:
vstr = "char";
break;
case V_EVFLAG:
case V_NONE:
vstr = NULL;
break;
default:
vstr = "int";
break;
}
if (vstr == NULL)
continue;
if (reent_opt)
printf("\t");
else
printf("static ");
printf("%s\t", vstr);
if (vp->class == VC_POINTER || vp->class == VC_ARRAYP)
printf("*");
printf("%s", vp->name);
if (vp->class == VC_ARRAY1 || vp->class == VC_ARRAYP)
printf("[%d]", vp->length1);
else if (vp->class == VC_ARRAY2)
printf("[%d][%d]", vp->length1, vp->length2);
if (vp->type == V_STRING)
printf("[MAX_STRING_SIZE]");
if (vp->value != NULL)
printf(" = %s", vp->value);
printf(";\n");
}
if (reent_opt)
printf("};\n");
return;
}
/* Generate definition C code (C code in definition section) */
gen_defn_c_code()
{
extern Expr *defn_c_list;
Expr *ep;
ep = defn_c_list;
if (ep != NULL)
{
printf("\n\t/* C code definitions */\n");
for (; ep != NULL; ep = ep->next)
{
print_line_num(ep->line_num, ep->src_file);
printf("%s\n", ep->left);
}
}
return;
}
/* Generate global C code (C code following state program) */
gen_global_c_code()
{
extern Expr *global_c_list;
Expr *ep;
ep = global_c_list;
if (ep != NULL)
{
printf("\f\t/* Global C code */\n");
print_line_num(ep->line_num, ep->src_file);
for (; ep != NULL; ep = ep->next)
{
printf("%s\n", ep->left);
}
}
return;
}
/* Sets cp->index for each variable, & returns number of db channels defined.
*/
db_chan_count()
{
extern Chan *chan_list;
int nchan;
Chan *cp;
nchan = 0;
for (cp = chan_list; cp != NULL; cp = cp->next)
{
cp->index = nchan;
if (cp->num_elem == 0)
nchan += 1;
else
nchan += cp->num_elem; /* array with multiple channels */
}
return nchan;
}
/* Assign event bits to event flags and associate db channels with
* event flags.
*/
assign_ef_bits()
{
extern Var *var_list;
extern Chan *chan_list;
Var *vp;
Chan *cp;
extern int num_events;
int n;
/* Assign event flag numbers (starting at 1) */
printf("\n/* Event flags */\n");
num_events = 0;
for (vp = var_list; vp != NULL; vp = vp->next)
{
if (vp->type == V_EVFLAG)
{
num_events++;
vp->ef_num = num_events;
printf("#define %s\t%d\n", vp->name, num_events);
}
}
/* Associate event flags with DB channels */
for (cp = chan_list; cp != NULL; cp = cp->next)
{
if (cp->num_elem == 0)
{
if (cp->ef_var != NULL)
{
vp = cp->ef_var;
cp->ef_num = vp->ef_num;
}
}
else /* cp->num_elem != 0 */
{
for (n = 0; n < cp->num_elem; n++)
{
vp = cp->ef_var_list[n];
if (vp != NULL)
{
cp->ef_num_list[n] = vp->ef_num;
}
}
}
}
return;
}
/* Assign a delay id to each "delay()" in an event (when()) expression */
assign_delay_ids()
{
extern Expr *ss_list;
Expr *ssp, *sp, *tp;
int delay_id;
int assign_next_delay_id();
#ifdef DEBUG
fprintf(stderr, "assign_delay_ids:\n");
#endif /*DEBUG*/
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
{
for (sp = ssp->left; sp != 0; sp = sp->next)
{
/* Each state has it's own delay id's */
delay_id = 0;
for (tp = sp->left; tp != 0; tp = tp->next)
{ /* traverse event expression only */
traverseExprTree(tp->left, E_FUNC, "delay",
assign_next_delay_id, &delay_id);
}
/* Keep track of number of delay id's requied */
if (delay_id > max_delays)
max_delays = delay_id;
}
}
}
assign_next_delay_id(ep, delay_id)
Expr *ep;
int *delay_id;
{
ep->right = (Expr *)*delay_id;
*delay_id += 1;
}
/* Traverse the expression tree, and call the supplied
* function whenever type = ep->type AND value matches ep->value.
* The condition value = 0 matches all.
* The function is called with the current ep and a supplied argument (argp) */
traverseExprTree(ep, type, value, funcp, argp)
Expr *ep; /* ptr to start of expression */
int type; /* to search for */
char *value; /* with optional matching value */
void (*funcp)(); /* function to call */
void *argp; /* ptr to argument to pass on to function */
{
Expr *ep1;
extern char *stype[];
if (ep == 0)
return;
if (printTree)
fprintf(stderr, "traverseExprTree: type=%s, value=%s\n",
stype[ep->type], ep->value);
/* Call the function? */
if ((ep->type == type) && (value == 0 || strcmp(ep->value, value) == 0) )
{
funcp(ep, argp);
}
/* Continue traversing the expression tree */
switch(ep->type)
{
case E_VAR:
case E_CONST:
case E_STRING:
case E_TEXT:
case E_BREAK:
break;
case E_PAREN:
case E_UNOP:
case E_SS:
case E_STATE:
case E_FUNC:
case E_COMMA:
case E_CMPND:
case E_STMT:
case E_ELSE:
case E_PRE:
case E_POST:
for (ep1 = ep->left; ep1 != 0; ep1 = ep1->next)
{
traverseExprTree(ep1, type, value, funcp, argp);
}
break;
case E_WHEN:
case E_ASGNOP:
case E_BINOP:
case E_SUBSCR:
case E_IF:
case E_WHILE:
case E_FOR:
case E_X:
for (ep1 = ep->left; ep1 != 0; ep1 = ep1->next)
{
traverseExprTree(ep1, type, value, funcp, argp);
}
for (ep1 = ep->right; ep1 != 0; ep1 = ep1->next)
{
traverseExprTree(ep1, type, value, funcp, argp);
}
break;
default:
fprintf(stderr, "traverseExprTree: type=%d???\n", ep->type);
}
}
-196
View File
@@ -1,196 +0,0 @@
/* /share/epicsH %W% %G%
*
* DESCRIPTION: Definitions for the run-time sequencer.
*
* Author: Andy Kozubal
* Date:
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991,2,3, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* 07mar91,ajk Changed SSCB semaphore id names.
* 05jul91,ajk Added function prototypes.
* 16dec91,ajk Setting up for VxWorks version 5.
* 27apr92,ajk Changed to new event flag mode (SSCB & PROG changed).
* 27apr92,ajk Removed getSemId from CHAN.
* 28apr92,ajk Implemented new event flag mode.
* 17feb93,ajk Fixed some functions prototypes.
* 10jun93,ajk Removed VxWorks V4/V5 conditional compile.
* 20jul93,ajk Removed non-ANSI function definitions.
* 21mar94,ajk Implemented new i/f with snc (see seqCom.h).
* 21mar94,ajk Implemented assignment of array elements to db. Also,
allow "unlimited" number of channels.
* 28mar94,ajk Added time stamp support.
* 29mar94,ajk Added dbOffset in db_channel structure; allows faster processing
of values returned with monitors and pvGet().
*/
#ifndef INCLseqh
#define INCLseqh
#ifndef TRUE
#include <ctype.h>
#endif
#include "seqCom.h"
#ifndef VOID
#include "cadef.h"
#include "db_access.h"
#include "alarm.h"
#include "vxWorks.h"
#include "ioLib.h"
#include "semLib.h"
#include "taskLib.h"
#endif
/* Structure to hold information about database channels */
struct db_channel
{
/* These are supplied by SNC */
char *dbAsName; /* channel name from assign statement */
char *pVar; /* ptr to variable */
char *pVarName; /* variable name string */
char *pVarType; /* variable type string (e.g. ("int") */
long count; /* number of elements in array */
long efId; /* event flag id if synced */
long eventNum; /* event number */
BOOL monFlag; /* TRUE if channel is to be monitored */
/* These are filled in at run time */
char *dbName; /* channel name after macro expansion */
long index; /* index in array of db channels */
chid chid; /* ptr to channel id (from ca_search()) */
BOOL assigned; /* TRUE only if channel is assigned */
BOOL connected; /* TRUE only if channel is connected */
BOOL getComplete; /* TRUE if previous pvGet completed */
short dbOffset; /* Offset to value in db access structure */
short status; /* last db access status code */
TS_STAMP timeStamp; /* time stamp */
long dbCount; /* actual count for db access */
short severity; /* last db access severity code */
short size; /* size (in bytes) of single variable element */
short getType; /* db get type (e.g. DBR_STS_INT) */
short putType; /* db put type (e.g. DBR_INT) */
BOOL monitored; /* TRUE if channel IS monitored */
evid evid; /* event id (supplied by CA) */
SEM_ID getSemId; /* semaphore id for async get */
struct state_program *sprog; /* state program that owns this structure */
};
typedef struct db_channel CHAN;
/* Structure to hold information about a state */
struct state_info_block
{
char *pStateName; /* state name */
ACTION_FUNC actionFunc; /* ptr to action routine for this state */
EVENT_FUNC eventFunc; /* ptr to event routine for this state */
DELAY_FUNC delayFunc; /* ptr to delay setup routine for this state */
bitMask *pEventMask; /* event mask for this state */
};
typedef struct state_info_block STATE;
#define MAX_NDELAY 20 /* max # delays allowed in each SS */
/* Structure to hold information about a State Set */
struct state_set_control_block
{
char *pSSName; /* state set name (for debugging) */
long taskId; /* task id */
long taskPriority; /* task priority */
SEM_ID syncSemId; /* semaphore for event sync */
SEM_ID getSemId; /* semaphore for synchronous pvGet() */
long numStates; /* number of states */
STATE *pStates; /* ptr to array of state blocks */
short currentState; /* current state index */
short nextState; /* next state index */
short prevState; /* previous state index */
short errorState; /* error state index (-1 if none defined) */
short transNum; /* highest priority trans. # that triggered */
bitMask *pMask; /* current event mask */
long numDelays; /* number of delays activated */
ULONG delay[MAX_NDELAY]; /* queued delay value in tics */
BOOL delayExpired[MAX_NDELAY]; /* TRUE if delay expired */
ULONG timeEntered; /* time that a state was entered */
struct state_program *sprog; /* ptr back to state program block */
};
typedef struct state_set_control_block SSCB;
/* Macro table */
typedef struct macro {
char *pName;
char *pValue;
} MACRO;
/* All information about a state program.
The address of this structure is passed to the run-time sequencer:
*/
struct state_program
{
char *pProgName; /* program name (for debugging) */
long taskId; /* task id (main task) */
BOOL task_is_deleted;/* TRUE if main task has been deleted */
long taskPriority; /* task priority */
SEM_ID caSemId; /* semiphore for locking CA events */
CHAN *pChan; /* table of channels */
long numChans; /* number of db channels, incl. unassigned */
long assignCount; /* number of db channels assigned */
long connCount; /* number of channels connected */
SSCB *pSS; /* array of state set control blocks */
long numSS; /* number of state sets */
char *pVar; /* ptr to user variable area */
long varSize; /* # bytes in user variable area */
MACRO *pMacros; /* ptr to macro table */
char *pParams; /* program paramters */
bitMask *pEvents; /* event bits for event flags & db */
long numEvents; /* number of events */
long options; /* options (bit-encoded) */
EXIT_FUNC exitFunc; /* exit function */
SEM_ID logSemId; /* logfile locking semaphore */
long logFd; /* logfile file descr. */
};
typedef struct state_program SPROG;
#define MAX_MACROS 50
/* Task parameters */
#define SPAWN_STACK_SIZE 10000
#define SPAWN_OPTIONS VX_DEALLOC_STACK | VX_FP_TASK | VX_STDIO
#define SPAWN_PRIORITY 100
/* Function declarations for internal sequencer funtions */
long seqConnect (SPROG *);
VOID seqEventHandler (struct event_handler_args);
VOID seqConnHandler (struct connection_handler_args);
VOID seqCallbackHandler(struct event_handler_args);
VOID seqWakeup (SPROG *, long);
long seq (struct seqProgram *, char *, long);
VOID seqFree (SPROG *);
long sequencer (SPROG *, long, char *);
VOID ssEntry (SPROG *, SSCB *);
long sprogDelete (long);
long seqMacParse (char *, SPROG *);
char *seqMacValGet (MACRO *, char *);
VOID seqMacEval (char *, char *, long, MACRO *);
STATUS seq_log ();
SPROG *seqFindProg (long);
#endif /*INCLseqh*/
-158
View File
@@ -1,158 +0,0 @@
/* * base/include seqCom.h,v 1.3 1995/10/10 01:25:08 wright Exp
*
* DESCRIPTION: Common definitions for state programs and run-time sequencer.
*
* Author: Andy Kozubal
* Date: 01mar94
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1993 the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
* Modification Log:
* -----------------
* 11jul96,ajk Changed all int types to long.
* 22jul96,ajk Changed PFUNC to ACTION_FUNC, EVENT_FUNC, DELAY_FUNC, & EXIT_FUNC.
*
*/
#ifndef INCLseqComh
#define INCLseqComh
#define MAGIC 940501 /* current magic number for SPROG */
#include "tsDefs.h" /* time stamp defs */
#include "stdio.h" /* standard i/o defs */
/* Bit encoding for run-time options */
#define OPT_DEBUG (1<<0) /* turn on debugging */
#define OPT_ASYNC (1<<1) /* use async. gets */
#define OPT_CONN (1<<2) /* wait for all connections */
#define OPT_REENT (1<<3) /* generate reentrant code */
#define OPT_NEWEF (1<<4) /* new event flag mode */
#define OPT_TIME (1<<5) /* get time stamps */
#define OPT_VXWORKS (1<<6) /* include VxWorks files */
/* Macros to handle set & clear event bits */
#define NBITS 32 /* # bits in bitMask word */
typedef long bitMask;
#define bitSet(word, bitnum) (word[(bitnum)/NBITS] |= (1<<((bitnum)%NBITS)))
#define bitClear(word, bitnum) (word[(bitnum)/NBITS] &= ~(1<<((bitnum)%NBITS)))
#define bitTest(word, bitnum) ((word[(bitnum)/NBITS] & (1<<((bitnum)%NBITS))) != 0)
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif /*TRUE*/
typedef long SS_ID; /* state set id */
/* Prototype for action, event, delay, and exit functions */
typedef long (*PFUNC)();
typedef void (*ACTION_FUNC)();
typedef long (*EVENT_FUNC)();
typedef void (*DELAY_FUNC)();
typedef void (*EXIT_FUNC)();
#ifdef OFFSET
#undef OFFSET
#endif
/* The OFFSET macro calculates the byte offset of a structure member
* from the start of a structure */
#define OFFSET(structure, member) ((long) &(((structure *) 0) -> member))
/* Structure to hold information about database channels */
struct seqChan
{
char *dbAsName; /* assigned channel name */
void *pVar; /* ptr to variable (-r option)
* or structure offset (+r option) */
char *pVarName; /* variable name, including subscripts */
char *pVarType; /* variable type, e.g. "int" */
long count; /* element count for arrays */
long eventNum; /* event number for this channel */
long efId; /* event flag id if synced */
long monFlag; /* TRUE if channel is to be monitored */
};
/* Structure to hold information about a state */
struct seqState
{
char *pStateName; /* state name */
ACTION_FUNC actionFunc; /* action routine for this state */
EVENT_FUNC eventFunc; /* event routine for this state */
DELAY_FUNC delayFunc; /* delay setup routine for this state */
bitMask *pEventMask; /* event mask for this state */
};
/* Structure to hold information about a State Set */
struct seqSS
{
char *pSSName; /* state set name */
struct seqState *pStates; /* array of state blocks */
long numStates; /* number of states in this state set */
long errorState; /* error state index (-1 if none defined) */
};
/* All information about a state program */
struct seqProgram
{
long magic; /* magic number */
char *pProgName; /* program name (for debugging) */
struct seqChan *pChan; /* table of channels */
long numChans; /* number of db channels */
struct seqSS *pSS; /* array of state set info structs */
long numSS; /* number of state sets */
long varSize; /* # bytes in user variable area */
char *pParams; /* program paramters */
long numEvents; /* number of event flags */
long options; /* options (bit-encoded) */
EXIT_FUNC exitFunc; /* exit function */
};
/*
* Function declarations for interface between state program & sequencer.
* Notes:
* "seq_" is added by SNC to guarantee global uniqueness.
* These functions appear in the module seq_if.c.
* The SNC must generate these modules--see gen_ss_code.c.
*/
void seq_efSet(SS_ID, long); /* set an event flag */
long seq_efTest(SS_ID, long); /* test an event flag */
long seq_efClear(SS_ID, long); /* clear an event flag */
long seq_efTestAndClear(SS_ID, long);/* test & clear an event flag */
long seq_pvGet(SS_ID, long); /* get pv value */
long seq_pvPut(SS_ID, long); /* put pv value */
TS_STAMP seq_pvTimeStamp(SS_ID, long); /* get time stamp value */
long seq_pvAssign(SS_ID, long, char *);/* assign/connect to a pv */
long seq_pvMonitor(SS_ID, long); /* enable monitoring on pv */
long seq_pvStopMonitor(SS_ID, long); /* disable monitoring on pv */
long seq_pvStatus(SS_ID, long); /* returns pv alarm status code */
long seq_pvSeverity(SS_ID, long); /* returns pv alarm severity */
long seq_pvAssigned(SS_ID, long); /* returns TRUE if assigned */
long seq_pvConnected(SS_ID, long); /* TRUE if connected */
long seq_pvGetComplete(SS_ID, long); /* TRUE if last get completed */
long seq_pvChannelCount(SS_ID); /* returns number of channels */
long seq_pvConnectCount(SS_ID); /* returns number of channels connected */
long seq_pvAssignCount(SS_ID); /* returns number of channels assigned */
long seq_pvCount(SS_ID, long); /* returns number of elements in array */
void seq_pvFlush(); /* flush put/get requests */
long seq_pvIndex(SS_ID, long); /* returns index of pv */
long seq_seqLog(); /* Logging: variable number of parameters */
void seq_delayInit(SS_ID, long, float);/* initialize a delay entry */
long seq_delay(SS_ID, long); /* test a delay entry */
char *seq_macValueGet(SS_ID, char *); /* Given macro name, return ptr to value */
long seq_optGet (SS_ID ssId, char *opt); /* check an option for TRUE/FALSE */
#endif /*INCLseqComh*/
-313
View File
@@ -1,313 +0,0 @@
/*
seq_ca.c,v 1.2 1995/06/27 15:25:54 wright Exp
* DESCRIPTION: Channel access interface for sequencer.
*
* Author: Andy Kozubal
* Date: July, 1991
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991-1994, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* 03jul91,ajk .
* 11dec91,ajk Cosmetic changes (comments & names)
* 13feb92,ajk All seqLog() calls compile only if DEBUG is defined.
* 28apr92,ajk Implemented new event flag mode.
* 21may92,ajk Will periodically announce number of connected channels
* if waiting form some to connect.
* 17feb93,ajk Implemented code to allow sharing of a single CA task by
* all state programs. Added seq_disconnect() and ca_import_cancel().
DB name resolution was moved to seq_main.c.
* 19feb93,ajk Added patched version of VxWorks 5.02b taskVarDelete().
* 01mar94,ajk Moved "seq_pv*()" functions to seq_if.c.
* 28mar94,ajk Restructured event& callback handlers to call proc_db_events().
* 29mar94,ajk Removed getPtrToValue(). Offset is now in db_channel structure.
* 08apr94,ajk Added support for time stamp.
* 17jan96,ajk Removed ca_import_cancel(), which is now in channel access lib.
* 17jan96,ajk Many routines changed to use ANSI-style function headers.
*/
#define ANSI
#include "seq.h"
#include "string.h"
#include "taskVarLib.h"
LOCAL VOID proc_db_events(union db_access_val *, CHAN *, long);
/*#define DEBUG*/
#ifdef DEBUG
#undef LOCAL
#define LOCAL
#endif /*DEBUG*/
/*
* seq_connect() - Connect to all database channels through channel access.
*/
long seq_connect(SPROG *pSP)
{
CHAN *pDB;
int status, i;
extern VOID seq_conn_handler();
/*
* For each channel: connect to db & isssue monitor (if monFlag is TRUE).
*/
for (i = 0, pDB = pSP->pChan; i < pSP->numChans; i++, pDB++)
{
if (pDB->dbName == NULL || pDB->dbName[0] == 0)
continue; /* skip records without pv names */
pDB->assigned = TRUE;
pSP->assignCount += 1; /* keep track of number of *assigned* channels */
#ifdef DEBUG
logMsg("seq_connect: connect %s to %s\n",
pDB->pVarName, pDB->dbName);
#endif /*DEBUG*/
/* Connect to it */
status = ca_build_and_connect(
pDB->dbName, /* DB channel name */
TYPENOTCONN, /* Don't get initial value */
0, /* get count (n/a) */
&(pDB->chid), /* ptr to chid */
0, /* ptr to value (n/a) */
seq_conn_handler, /* connection handler routine */
pDB); /* user ptr is CHAN structure */
if (status != ECA_NORMAL)
{
SEVCHK(status, "ca_search");
ca_task_exit();
return -1;
}
/* Clear monitor indicator */
pDB->monitored = FALSE;
/*
* Issue monitor request
*/
if (pDB->monFlag)
{
seq_pvMonitor((SS_ID)pSP->pSS, i);
}
}
ca_flush_io();
return 0;
}
#define GET_COMPLETE 0
#define MON_COMPLETE 1
/*
* seq_event_handler() - Channel access events (monitors) come here.
* args points to CA event handler argument structure. args.usr contains
* a pointer to the channel structure (CHAN *).
*/
VOID seq_event_handler(struct event_handler_args args)
{
/* Process event handling in each state set */
proc_db_events((union db_access_val *)args.dbr, (CHAN *)args.usr, MON_COMPLETE);
return;
}
/*
* seq_callback_handler() - Sequencer callback handler.
* Called when a "get" completes.
* args.usr points to the db structure (CHAN *) for tis channel.
*/
VOID seq_callback_handler(struct event_handler_args args)
{
/* Process event handling in each state set */
proc_db_events((union db_access_val *)args.dbr, (CHAN *)args.usr, GET_COMPLETE);
return;
}
/* Common code for event and callback handling */
LOCAL VOID proc_db_events(union db_access_val *pAccess, CHAN *pDB, long complete_type)
{
SPROG *pSP;
void *pVal;
#ifdef DEBUG
logMsg("proc_db_events: var=%s, pv=%s\n", pDB->VarName, pDB->dbName);
#endif /*DEBUG*/
/* Copy value returned into user variable */
pVal = (void *)((long)pAccess + pDB->dbOffset); /* ptr to data in CA structure */
bcopy(pVal, pDB->pVar, pDB->size * pDB->dbCount);
/* Copy status & severity */
pDB->status = pAccess->tchrval.status;
pDB->severity = pAccess->tchrval.severity;
/* Copy time stamp */
pDB->timeStamp = pAccess->tchrval.stamp;
/* Get ptr to the state program that owns this db entry */
pSP = pDB->sprog;
/* Indicate completed pvGet() */
if (complete_type == GET_COMPLETE)
{
pDB->getComplete = TRUE;
}
/* Wake up each state set that uses this channel in an event */
seqWakeup(pSP, pDB->eventNum);
/* If there's an event flag associated with this channel, set it */
if (pDB-> efId > 0)
seq_efSet((SS_ID)pSP->pSS, pDB->efId);
/* Special processing for completed synchronous (-a) pvGet() */
if ( (complete_type == GET_COMPLETE) && ((pSP->options & OPT_ASYNC) == 0) )
semGive(pDB->getSemId);
return;
}
/* Disconnect all database channels */
/*#define DEBUG_DISCONNECT*/
long seq_disconnect(SPROG *pSP)
{
CHAN *pDB;
STATUS status;
int i;
extern int seqAuxTaskId;
SPROG *pMySP; /* will be NULL if this task is not a sequencer task */
/* Did we already disconnect? */
if (pSP->connCount < 0)
return 0;
/* Import Channel Access context from the auxillary seq. task */
pMySP = seqFindProg(taskIdSelf() );
if (pMySP == NULL)
{
status = ca_import(seqAuxTaskId); /* not a sequencer task */
SEVCHK (status, "seq_disconnect: ca_import");
}
pDB = pSP->pChan;
for (i = 0; i < pSP->numChans; i++, pDB++)
{
if (!pDB->assigned)
continue;
#ifdef DEBUG_DISCONNECT
logMsg("seq_disconnect: disconnect %s from %s\n",
pDB->pVarName, pDB->dbName);
taskDelay(30);
#endif /*DEBUG_DISCONNECT*/
/* Disconnect this channel */
status = ca_clear_channel(pDB->chid);
SEVCHK (status, "seq_disconnect: ca_clear_channel");
/* Clear monitor & connect indicators */
pDB->monitored = FALSE;
pDB->connected = FALSE;
}
pSP->connCount = -1; /* flag to indicate all disconnected */
ca_flush_io();
/* Cancel CA context if it was imported above */
if (pMySP == NULL)
{
#ifdef DEBUG_DISCONNECT
logMsg("seq_disconnect: ca_import_cancel\n");
#endif /*DEBUG_DISCONNECT*/
SEVCHK(ca_import_cancel(taskIdSelf()),
"seq_disconnect: ca_import_cancel() failed!");
}
return 0;
}
/*
* seq_conn_handler() - Sequencer connection handler.
* Called each time a connection is established or broken.
*/
VOID seq_conn_handler(struct connection_handler_args args)
{
CHAN *pDB;
SPROG *pSP;
/* User argument is db ptr (specified at ca_search() ) */
pDB = (CHAN *)ca_puser(args.chid);
/* State program that owns this db entry */
pSP = pDB->sprog;
/* Check for connected */
if (ca_field_type(args.chid) == TYPENOTCONN)
{
pDB->connected = FALSE;
pSP->connCount--;
pDB->monitored = FALSE;
#ifdef DEBUG
logMsg("%s disconnected from %s\n", pDB->VarName, pDB->dbName);
#endif /*DEBUG*/
}
else /* PV connected */
{
pDB->connected = TRUE;
pSP->connCount++;
if (pDB->monFlag)
pDB->monitored = TRUE;
#ifdef DEBUG
logMsg("%s connected to %s\n", pDB->VarName, pDB->dbName);
#endif /*DEBUG*/
pDB->dbCount = ca_element_count(args.chid);
if (pDB->dbCount > pDB->count)
pDB->dbCount = pDB->count;
}
/* Wake up each state set that is waiting for event processing */
seqWakeup(pSP, 0);
return;
}
/*
* seqWakeup() -- wake up each state set that is waiting on this event
* based on the current event mask. EventNum = 0 means wake all state sets.
*/
VOID seqWakeup(SPROG *pSP, long eventNum)
{
int nss;
SSCB *pSS;
/* Check event number against mask for all state sets: */
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
{
/* If event bit in mask is set, wake that state set */
if ( (eventNum == 0) || bitTest(pSS->pMask, eventNum) )
{
semGive(pSS->syncSemId); /* wake up the ss task */
}
}
return;
}
-580
View File
@@ -1,580 +0,0 @@
/*
seq_if.c,v 1.3 1995/10/10 01:56:49 wright Exp
* DESCRIPTION: Interface functions from state program to run-time sequencer.
* Note: To prevent global name conflicts "seq_" is added by the SNC, e.g.
* pvPut() becomes seq_pvPut().
*
* Author: Andy Kozubal
* Date: 1 March, 1994
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991-1994, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
*/
#include <string.h>
#define ANSI
#include "seq.h"
#include "tickLib.h"
#include "logLib.h"
/* See seqCom.h for function prototypes (ANSI standard) */
/*#define DEBUG*/
/* The following "pv" functions are included here:
seq_pvGet()
seq_pvGetComplete()
seq_pvPut()
seq_pvFlush()
seq_pvConnect()
seq_pvMonitor()
seq_pvStopMonitor()
seq_pvStatus()
seq_pvSeverity()
seq_pvConnected()
seq_pvAssigned()
seq_pvChannelCount()
seq_pvAssignCount()
seq_pvConnectCount()
seq_pvCount()
seq_pvIndex()
seq_pvTimeStamp()
*/
/* Flush outstanding CA requests */
void seq_pvFlush()
{
ca_flush_io();
}
/*
* seq_pvGet() - Get DB value (uses channel access).
*/
long seq_pvGet(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
SSCB *pSS;
CHAN *pDB; /* ptr to channel struct */
int status, sem_status;
extern VOID seq_callback_handler();
pSS = (SSCB *)ssId;
pSP = pSS->sprog;
pDB = pSP->pChan + pvId;
/* Check for channel connected */
if (!pDB->connected)
return ECA_DISCONN;
/* Flag this pvGet() as not completed */
pDB->getComplete = FALSE;
/* If synchronous pvGet then clear the pvGet pend semaphore */
if ((pSP->options & OPT_ASYNC) == 0)
{
pDB->getSemId = pSS->getSemId;
semTake(pSS->getSemId, NO_WAIT);
}
/* Perform the CA get operation with a callback routine specified */
status = ca_array_get_callback(
pDB->getType, /* db request type */
pDB->count, /* element count */
pDB->chid, /* chid */
seq_callback_handler
, /* callback handler */
pDB); /* user arg */
if (status != ECA_NORMAL)
{
pDB->getComplete = TRUE;
SEVCHK(status, "pvGet");
return status;
}
ca_flush_io();
if ((pSP->options & OPT_ASYNC) != 0)
{ /* +a option: return immediately */
return ECA_NORMAL;
}
/* Synchronous (-a option): wait for completion (10s timeout) */
sem_status = semTake(pSS->getSemId, 600);
if (sem_status != OK)
{
logMsg ("semTake error=%d\n", sem_status, 0,0,0,0,0);
return ECA_TIMEOUT;
}
return ECA_NORMAL;
}
/*
* seq_pvGetComplete() - returns TRUE if the last get completed.
*/
long seq_pvGetComplete(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->getComplete;
}
/*
* seq_pvPut() - Put DB value.
*/
long seq_pvPut(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
int status, count;
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
#ifdef DEBUG
logMsg("seq_pvPut: pv name=%s, pVar=0x%x\n", pDB->dbName, pDB->pVar, 0,0,0,0);
#endif /*DEBUG*/
if (!pDB->connected)
return ECA_DISCONN;
count = pDB->count;
if (count > pDB->dbCount)
count = pDB->dbCount; /* don't try to put more than db count */
status = ca_array_put(pDB->putType, count, pDB->chid, pDB->pVar);
#ifdef DEBUG
logMsg("seq_pvPut: status=%d\n", status, 0,0,0,0,0);
if (status != ECA_NORMAL)
{
seq_log(pSP, "pvPut on \"%s\" failed (%d)\n",
pDB->dbName, status);
seq_log(pSP, " putType=%d\n", pDB->putType);
seq_log(pSP, " size=%d, count=%d\n", pDB->size, count);
}
#endif /*DEBUG*/
return status;
}
/*
* seq_pvAssign() - Assign/Connect to a channel.
* Assign to a zero-lth string ("") disconnects/de-assignes.
*/
long seq_pvAssign(SS_ID ssId, long pvId, char *pvName)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
int status, nchar;
extern VOID seq_conn_handler();
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
#ifdef DEBUG
printf("Assign %s to \"%s\"\n", pDB->pVarName, pvName);
#endif /*DEBUG*/
if (pDB->assigned)
{ /* Disconnect this channel */
status = ca_clear_channel(pDB->chid);
if (status != ECA_NORMAL)
return status;
free(pDB->dbName);
pDB->assigned = FALSE;
pSP->assignCount -= 1;
}
if (pDB->connected)
{
pDB->connected = FALSE;
pSP->connCount -= 1;
}
pDB->monitored = FALSE;
nchar = strlen(pvName);
pDB->dbName = (char *)calloc(1, nchar + 1);
strcpy(pDB->dbName, pvName);
/* Connect */
if (nchar > 0)
{
pDB->assigned = TRUE;
pSP->assignCount += 1;
status = ca_build_and_connect(
pDB->dbName, /* DB channel name */
TYPENOTCONN, /* Don't get initial value */
0, /* get count (n/a) */
&(pDB->chid), /* ptr to chid */
0, /* ptr to value (n/a) */
seq_conn_handler, /* connection handler routine */
pDB); /* user ptr is CHAN structure */
if (status != ECA_NORMAL)
{
return status;
}
if (pDB->monFlag)
{
status = seq_pvMonitor(ssId, pvId);
if (status != ECA_NORMAL)
return status;
}
}
ca_flush_io();
return ECA_NORMAL;
}
/*
* seq_pvMonitor() - Initiate a monitor on a channel.
*/
long seq_pvMonitor(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
int status;
extern VOID seq_event_handler();
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
#ifdef DEBUG
printf("monitor \"%s\"\n", pDB->dbName);
#endif /*DEBUG*/
if (pDB->monitored || !pDB->assigned)
return ECA_NORMAL;
status = ca_add_array_event(
pDB->getType, /* requested type */
pDB->count, /* element count */
pDB->chid, /* chid */
seq_event_handler, /* function to call */
pDB, /* user arg (db struct) */
0.0, /* pos. delta value */
0.0, /* neg. delta value */
0.0, /* timeout */
&pDB->evid); /* where to put event id */
if (status != ECA_NORMAL)
{
SEVCHK(status, "ca_add_array_event");
ca_task_exit(); /* this is serious */
return status;
}
ca_flush_io();
pDB->monitored = TRUE;
return ECA_NORMAL;
}
/*
* seq_pvStopMonitor() - Cancel a monitor
*/
long seq_pvStopMonitor(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
int status;
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
if (!pDB->monitored)
return -1;
status = ca_clear_event(pDB->evid);
if (status != ECA_NORMAL)
{
SEVCHK(status, "ca_clear_event");
return status;
}
pDB->monitored = FALSE;
return status;
}
/*
* seq_pvChannelCount() - returns total number of database channels.
*/
long seq_pvChannelCount(SS_ID ssId)
{
SPROG *pSP; /* ptr to state program */
pSP = ((SSCB *)ssId)->sprog;
return pSP->numChans;
}
/*
* seq_pvConnectCount() - returns number of database channels connected.
*/
long seq_pvConnectCount(SS_ID ssId)
{
SPROG *pSP; /* ptr to state program */
pSP = ((SSCB *)ssId)->sprog;
return pSP->connCount;
}
/*
* seq_pvAssignCount() - returns number of database channels assigned.
*/
long seq_pvAssignCount(SS_ID ssId)
{
SPROG *pSP; /* ptr to state program */
pSP = ((SSCB *)ssId)->sprog;
return pSP->assignCount;
}
/*
* seq_pvConnected() - returns TRUE if database channel is connected.
*/
long seq_pvConnected(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB;
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->connected;
}
/*
* seq_pvAssigned() - returns TRUE if database channel is assigned.
*/
long seq_pvAssigned(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB;
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->assigned;
}
/*
* seq_pvCount() - returns number elements in an array, which is the lesser of
* (1) the array size and (2) the element count returned by channel access.
*/
long seq_pvCount(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->dbCount;
}
/*
* seq_pvStatus() - returns channel alarm status.
*/
long seq_pvStatus(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->status;
}
/*
* seq_pvSeverity() - returns channel alarm severity.
*/
long seq_pvSeverity(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->severity;
}
/*
* seq_pvIndex() - returns index of database variable.
*/
long seq_pvIndex(SS_ID ssId, long pvId)
{
return pvId; /* index is same as pvId */
}
/*
* seq_pvTimeStamp() - returns channel time stamp.
*/
TS_STAMP seq_pvTimeStamp(SS_ID ssId, long pvId)
{
SPROG *pSP; /* ptr to state program */
CHAN *pDB; /* ptr to channel struct */
pSP = ((SSCB *)ssId)->sprog;
pDB = pSP->pChan + pvId;
return pDB->timeStamp;
}
/*
* seq_efSet() - Set an event flag, then wake up each state
* set that might be waiting on that event flag.
*/
VOID seq_efSet(SS_ID ssId, long ev_flag)
{
SPROG *pSP;
SSCB *pSS;
pSS = (SSCB *)ssId;
pSP = pSS->sprog;
#ifdef DEBUG
logMsg("seq_efSet: pSP=0x%x, pSS=0x%x, ev_flag=0x%x\n", pSP, pSS, ev_flag,
0,0,0);
taskDelay(10);
#endif /*DEBUG*/
/* Set this bit (apply resource lock) */
semTake(pSP->caSemId, WAIT_FOREVER);
bitSet(pSP->pEvents, ev_flag);
/* Wake up state sets that are waiting for this event flag */
seqWakeup(pSP, ev_flag);
/* Unlock resource */
semGive(pSP->caSemId);
}
/*
* seq_efTest() - Test event flag against outstanding events.
*/
long seq_efTest(SS_ID ssId, long ev_flag)
/* event flag */
{
SPROG *pSP;
SSCB *pSS;
int isSet;
pSS = (SSCB *)ssId;
pSP = pSS->sprog;
isSet = bitTest(pSP->pEvents, ev_flag);
#ifdef DEBUG
logMsg("seq_efTest: ev_flag=%d, event=0x%x, isSet=%d\n",
ev_flag, pSP->pEvents[0], isSet, 0,0,0,0);
#endif /*DEBUG*/
return isSet;
}
/*
* seq_efClear() - Test event flag against outstanding events, then clear it.
*/
long seq_efClear(SS_ID ssId, long ev_flag)
{
SPROG *pSP;
SSCB *pSS;
int isSet;
pSS = (SSCB *)ssId;
pSP = pSS->sprog;
isSet = bitTest(pSP->pEvents, ev_flag);
bitClear(pSP->pEvents, ev_flag);
return isSet;
}
/*
* seq_efTestAndClear() - Test event flag against outstanding events, then clear it.
*/
long seq_efTestAndClear(SS_ID ssId, long ev_flag)
{
SPROG *pSP;
SSCB *pSS;
int isSet;
pSS = (SSCB *)ssId;
pSP = pSS->sprog;
isSet = bitTest(pSP->pEvents, ev_flag);
bitClear(pSP->pEvents, ev_flag);
return isSet;
}
/* seq_delay() - test for delay() time-out expired */
long seq_delay(SS_ID ssId, long delayId)
{
SSCB *pSS;
ULONG timeElapsed;
pSS = (SSCB *)ssId;
/* Calc. elapsed time since state was entered */
timeElapsed = tickGet() - pSS->timeEntered;
/* Check for delay timeout */
if (timeElapsed >= pSS->delay[delayId])
{
pSS->delayExpired[delayId] = TRUE; /* mark as expired */
return TRUE;
}
return FALSE;
}
/*
* seq_delayInit() - initialize delay time (in seconds) on entering a state.
*/
VOID seq_delayInit(SS_ID ssId, long delayId, float delay)
{
SSCB *pSS;
int ndelay;
pSS = (SSCB *)ssId;
/* Convert delay time to tics & save */
pSS->delay[delayId] = delay * 60.0;
ndelay = delayId + 1;
if (ndelay > pSS->numDelays)
pSS->numDelays = ndelay;
}
/*
* seq_optGet: return the value of an option (e.g. "a").
* FALSE means "-" and TRUE means "+".
*/
long seq_optGet(SS_ID ssId, char *opt)
{
SPROG *pSP;
pSP = ((SSCB *)ssId)->sprog;
switch (opt[0])
{
case 'a': return ( (pSP->options & OPT_ASYNC) != 0);
case 'c': return ( (pSP->options & OPT_CONN) != 0);
case 'd': return ( (pSP->options & OPT_DEBUG) != 0);
case 'e': return ( (pSP->options & OPT_NEWEF) != 0);
case 'r': return ( (pSP->options & OPT_REENT) != 0);
case 'v': return ( (pSP->options & OPT_VXWORKS) != 0);
default: return FALSE;
}
}
-321
View File
@@ -1,321 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
seq_mac.c,v 1.2 1995/06/27 15:25:56 wright Exp
DESCRIPTION: Macro routines for Sequencer.
The macro table contains name & value pairs. These are both pointers
to strings.
ENVIRONMENT: VxWorks
HISTORY:
01mar94,ajk Added seq_macValueGet() as state program interface routine.
***************************************************************************/
#define ANSI
#include "seq.h"
#include "string.h"
LOCAL int seqMacParseName(char *);
LOCAL int seqMacParseValue(char *);
LOCAL char *skipBlanks(char *);
LOCAL MACRO *seqMacTblGet(MACRO *, char *);
/*#define DEBUG*/
/*
*seqMacEval - substitute macro value into a string containing:
* ....{mac_name}....
*/
VOID seqMacEval(pInStr, pOutStr, maxChar, pMac)
char *pInStr;
char *pOutStr;
long maxChar;
MACRO *pMac;
{
char name[50], *pValue, *pTmp;
int nameLth, valLth;
#ifdef DEBUG
logMsg("seqMacEval: InStr=%s\n", pInStr);
taskDelay(30);
#endif
pTmp = pOutStr;
while (*pInStr != 0 && maxChar > 0)
{
if (*pInStr == '{')
{ /* Do macro substitution */
pInStr++; /* points to macro name */
/* Copy the macro name */
nameLth = 0;
while (*pInStr != '}' && *pInStr != 0)
{
name[nameLth] = *pInStr++;
if (nameLth < (sizeof(name) - 1))
nameLth++;
}
name[nameLth] = 0;
if (*pInStr != 0)
pInStr++;
#ifdef DEBUG
logMsg("Macro name=%s\n", name);
taskDelay(30);
#endif
/* Find macro value from macro name */
pValue = seqMacValGet(pMac, name);
if (pValue != NULL)
{ /* Substitute macro value */
valLth = strlen(pValue);
if (valLth > maxChar)
valLth = maxChar;
#ifdef DEBUG
logMsg("Value=%s\n", pValue);
#endif
strncpy(pOutStr, pValue, valLth);
maxChar -= valLth;
pOutStr += valLth;
}
}
else
{ /* Straight susbstitution */
*pOutStr++ = *pInStr++;
maxChar--;
}
}
*pOutStr = 0;
#ifdef DEBUG
logMsg("OutStr=%s\n", pTmp);
taskDelay(30);
#endif
}
/*
* seq_macValueGet - given macro name, return pointer to its value.
*/
char *seq_macValueGet(ssId, pName)
SS_ID ssId;
char *pName;
{
SPROG *pSP;
MACRO *pMac;
pSP = ((SSCB *)ssId)->sprog;
pMac = pSP->pMacros;
return seqMacValGet(pMac, pName);
}
/*
* seqMacValGet - internal routine to convert macro name to macro value.
*/
char *seqMacValGet(pMac, pName)
MACRO *pMac;
char *pName;
{
int i;
#ifdef DEBUG
logMsg("seqMacValGet: name=%s", pName);
#endif /*DEBUG*/
for (i = 0 ; i < MAX_MACROS; i++, pMac++)
{
if (pMac->pName != NULL)
{
if (strcmp(pName, pMac->pName) == 0)
{
#ifdef DEBUG
logMsg(", value=%s\n", pMac->pValue);
#endif /*DEBUG*/
return pMac->pValue;
}
}
}
#ifdef DEBUG
logMsg(", no value\n");
#endif /*DEBUG*/
return NULL;
}
/*
* seqMacParse - parse the macro definition string and build
* the macro table (name/value pairs). Returns number of macros parsed.
* Assumes the table may already contain entries (values may be changed).
* String for name and value are allocated dynamically from pool.
*/
long seqMacParse(pMacStr, pSP)
char *pMacStr; /* macro definition string */
SPROG *pSP;
{
int nChar;
char *skipBlanks();
MACRO *pMac; /* macro table */
MACRO *pMacTbl; /* macro tbl entry */
char *pName, *pValue;
pMac = pSP->pMacros;
for ( ;; )
{
/* Skip blanks */
pMacStr = skipBlanks(pMacStr);
/* Parse the macro name */
nChar = seqMacParseName(pMacStr);
if (nChar == 0)
break; /* finished or error */
pName = (char *)calloc(nChar+1, 1);
if (pName == NULL)
break;
bcopy(pMacStr, pName, nChar);
pName[nChar] = 0;
#ifdef DEBUG
logMsg("name=%s, nChar=%d\n", pName, nChar);
taskDelay(30);
#endif
pMacStr += nChar;
/* Find a slot in the table */
pMacTbl = seqMacTblGet(pMac, pName);
if (pMacTbl == NULL)
break; /* table is full */
if (pMacTbl->pName == NULL)
{ /* Empty slot, insert macro name */
pMacTbl->pName = pName;
}
/* 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 = seqMacParseValue(pMacStr);
if (nChar == 0)
break;
/* Remove previous value if it exists */
pValue = pMacTbl->pValue;
if (pValue != NULL)
free(pValue);
/* Copy value string into newly allocated space */
pValue = (char *)calloc(nChar+1, 1);
if (pValue == NULL)
break;
pMacTbl->pValue = pValue;
bcopy(pMacStr, pValue, nChar);
pValue[nChar] = 0;
#ifdef DEBUG
logMsg("value=%s, nChar=%d\n", pValue, nChar);
taskDelay(30);
#endif
/* Skip past last value and over blanks and comma */
pMacStr += nChar;
pMacStr = skipBlanks(pMacStr);
if (*pMacStr++ != ',')
break;
}
if (*pMacStr == 0)
return 0;
else
return -1;
}
/*
* seqMacParseName() - Parse a macro name from the input string.
*/
LOCAL int seqMacParseName(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;
}
/*
* seqMacParseValue() - Parse a macro value from the input string.
*/
LOCAL int seqMacParseValue(pStr)
char *pStr;
{
int nChar;
nChar = 0;
/* Character string terminates on blank, comma, or EOS */
while ( (*pStr != ' ') && (*pStr != ',') && (*pStr != 0) )
{
pStr++;
nChar++;
}
return nChar;
}
/* skipBlanks() - skip blank characters */
LOCAL char *skipBlanks(pChar)
char *pChar;
{
while (*pChar == ' ')
pChar++;
return pChar;
}
/*
* seqMacTblGet - find a match for the specified name, otherwise
* return an empty slot in macro table.
*/
LOCAL MACRO *seqMacTblGet(pMac, pName)
MACRO *pMac;
char *pName; /* macro name */
{
int i;
MACRO *pMacTbl;
#ifdef DEBUG
logMsg("seqMacTblGet: name=%s\n", pName);
taskDelay(30);
#endif
for (i = 0, pMacTbl = pMac; i < MAX_MACROS; i++, pMacTbl++)
{
if (pMacTbl->pName != NULL)
{
if (strcmp(pName, pMacTbl->pName) == 0)
{
return pMacTbl;
}
}
}
/* Not found, find an empty slot */
for (i = 0, pMacTbl = pMac; i < MAX_MACROS; i++, pMacTbl++)
{
if (pMacTbl->pName == NULL)
{
return pMacTbl;
}
}
/* No empty slots available */
return NULL;
}
-652
View File
@@ -1,652 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990-1994, The Regents of the University of California
and the University of Chicago.
Los Alamos National Laboratory
seq_main.c,v 1.2 1995/06/27 15:25:58 wright Exp
DESCRIPTION: Seq() initiates a sequence as a group of cooperating
tasks. An optional string parameter specifies the values for
macros. The channel access context and task are shared by all state
programs.
ENVIRONMENT: VxWorks
HISTORY:
23apr91,ajk Fixed problem with state program invoking the sequencer.
01jul91,ajk Added ANSI functional prototypes.
05jul91,ajk Changed semCreate() in three places to semBCreate.
Modified semTake() second param. to WAIT_FOREVER.
These provide VX5.0 compatability.
16aug91,ajk Improved "magic number" error message.
25oct91,ajk Code to create semaphores "pSS->getSemId" was left out.
Added this code to init_sscb().
25nov91,ajk Removed obsolete seqLog() code dealing with global locking.
04dec91,ajk Implemented state program linked list, eliminating need for
task variables.
11dec91,ajk Cleaned up comments.
05feb92,ajk Decreased minimum allowable stack size to SPAWN_STACK_SIZE/2.
24feb92,ajk Print error code for log file failure.
28apr92,ajk Implemented new event flag mode.
29apr92,ajk Now alocates private program structures, even when reentry option
is not specified. This avoids problems with seqAddTask().
29apr92,ajk Implemented mutual exclusion lock in seq_log().
16feb93,ajk Converted to single channel access task for all state programs.
16feb93,ajk Removed VxWorks pre-v5 stuff.
17feb93,ajk Evaluation of channel names moved here from seq_ca.c.
19feb93,ajk Fixed time stamp format for seq_log().
16jun93,ajk Fixed taskSpawn() to have 15 args per vx5.1.
20jul93,ajk Replaced obsolete delete() with remove() per vx5.1 release notes.
20jul93,ajk Removed #define ANSI
15mar94,ajk Implemented i/f to snc through structures in seqCom.h.
15mar94,ajk Allowed assignment of array elements to db.
15mar94,ajk Rearranged code that builds program structures.
02may94,ajk Performed initialization when sequencer is evoked, even w/o
parameters.
19jul95,ajk Added unsigned types (unsigned char, short, int, long).
20jul95,ajk Added priority specification at run time.
03aug95,ajk Fixed problem with +r option: user variable space (pSP->pVar)
was not being allocated.
03jun96,ajk Now compiles with -wall and -pedantic switches.
***************************************************************************/
/*#define DEBUG 1*/
#include <string.h>
#include "seqCom.h"
#include "seq.h"
#include "taskLib.h"
#include "taskHookLib.h"
#include "logLib.h"
#include "errnoLib.h"
#include "usrLib.h"
#ifdef DEBUG
#undef LOCAL
#define LOCAL
#endif /*DEBUG*/
/* ANSI functional prototypes for local routines */
LOCAL SPROG *seqInitTables(struct seqProgram *);
LOCAL VOID init_sprog(struct seqProgram *, SPROG *);
LOCAL VOID init_sscb(struct seqProgram *, SPROG *);
LOCAL VOID init_chan(struct seqProgram *, SPROG *);
LOCAL VOID init_mac(SPROG *);
LOCAL VOID seq_logInit(SPROG *);
LOCAL VOID seqChanNameEval(SPROG *);
LOCAL VOID selectDBtype(char *, short *, short *, short *, short *);
#define SCRATCH_SIZE (MAX_MACROS*(MAX_STRING_SIZE+1)*12)
/* Globals */
/* Flag to indicate that "taskDeleteHookAdd()" was called */
int seqDeleteHookAdded = FALSE;
/* Auxillary sequencer task id; used to share CA context. */
int seqAuxTaskId = 0;
/*
* seq: User-callable routine to initiate a state program.
* Usage: seq(<pSP>, <macros string>, <stack size>)
* pSP is the ptr to the state program structure.
* Example: seq(&myprog, "logfile=mylog", 0)
* When called from the shell, the 2nd & 3rd parameters are optional.
*
* Creates the initial state program task and returns its task id.
* Most initialization is performed here.
*/
long seq (pSeqProg, macro_def, stack_size)
struct seqProgram *pSeqProg; /* state program info generated by snc */
char *macro_def; /* optional macro def'n string */
long stack_size; /* optional stack size (bytes) */
{
int tid;
extern sprog_delete(); /* Task delete routine */
extern char *seqVersion;
SPROG *pSP;
char *pValue, *ptask_name;
extern seqAuxTask();
/* Print version & date of sequencer */
printf("%s\n", seqVersion);
/* Spawn the sequencer auxillary task */
if (seqAuxTaskId == 0)
{
taskSpawn("seqAux", SPAWN_PRIORITY-1, VX_FP_TASK, 4000, seqAuxTask,
0,0,0,0,0,0,0,0,0,0);
while (seqAuxTaskId == 0)
taskDelay(5); /* wait for task to init. ch'l access */
#ifdef DEBUG
logMsg("task seqAux spawned, tid=0x%x\n", seqAuxTaskId, 0,0,0,0,0);
#endif /*DEBUG*/
}
/* Specify a routine to run at task delete */
if (!seqDeleteHookAdded)
{
taskDeleteHookAdd(sprog_delete);
seqDeleteHookAdded = TRUE;
}
/* Exit if no parameters specified */
if (pSeqProg == 0)
{
return 0;
}
/* Check for correct state program format */
if (pSeqProg->magic != MAGIC)
{ /* Oops */
logMsg("Illegal magic number in state program.\n", 0,0,0,0,0,0);
logMsg(" - Possible mismatch between SNC & SEQ versions\n", 0,0,0,0,0,0);
logMsg(" - Re-compile your program?\n", 0,0,0,0,0,0);
return -1;
}
/* Initialize the sequencer tables */
pSP = seqInitTables(pSeqProg);
/* Parse the macro definitions from the "program" statement */
seqMacParse(pSeqProg->pParams, pSP);
/* Parse the macro definitions from the command line */
seqMacParse(macro_def, pSP);
/* Do macro substitution on channel names */
seqChanNameEval(pSP);
/* Initialize sequencer logging */
seq_logInit(pSP);
/* Specify stack size */
if (stack_size == 0)
stack_size = SPAWN_STACK_SIZE;
pValue = seqMacValGet(pSP->pMacros, "stack");
if (pValue != NULL && strlen(pValue) > 0)
{
sscanf(pValue, "%ld", &stack_size);
}
if (stack_size < SPAWN_STACK_SIZE/2)
stack_size = SPAWN_STACK_SIZE/2;
/* Specify task name */
pValue = seqMacValGet(pSP->pMacros, "name");
if (pValue != NULL && strlen(pValue) > 0)
ptask_name = pValue;
else
ptask_name = pSP->pProgName;
/* Spawn the initial sequencer task */
#ifdef DEBUG
logMsg("Spawning task %s, stack_size=%d\n", ptask_name, stack_size, 0,0,0,0);
#endif /*DEBUG*/
/* Specify task priority */
pSP->taskPriority = SPAWN_PRIORITY;
pValue = seqMacValGet(pSP->pMacros, "priority");
if (pValue != NULL && strlen(pValue) > 0)
{
sscanf(pValue, "%ld", &(pSP->taskPriority));
}
if (pSP->taskPriority < SPAWN_PRIORITY)
pSP->taskPriority = SPAWN_PRIORITY;
if (pSP->taskPriority > 255)
pSP->taskPriority = 255;
tid = taskSpawn(ptask_name, pSP->taskPriority, SPAWN_OPTIONS,
stack_size, (FUNCPTR)sequencer, (int)pSP, stack_size, (int)ptask_name,
0,0,0,0,0,0,0);
seq_log(pSP, "Spawning state program \"%s\", task name = \"%s\"\n",
pSP->pProgName, ptask_name);
seq_log(pSP, " Task id = %d = 0x%x\n", tid, tid);
/* Return task id to calling program */
return tid;
}
/* seqInitTables - initialize sequencer tables */
LOCAL SPROG *seqInitTables(pSeqProg)
struct seqProgram *pSeqProg;
{
SPROG *pSP;
pSP = (SPROG *)calloc(1, sizeof (SPROG));
/* Initialize state program block */
init_sprog(pSeqProg, pSP);
/* Initialize state set control blocks */
init_sscb(pSeqProg, pSP);
/* Initialize database channel blocks */
init_chan(pSeqProg, pSP);
/* Initialize the macro table */
init_mac(pSP);
return pSP;
}
/*
* Copy data from seqCom.h structures into this task's dynamic structures as defined
* in seq.h.
*/
LOCAL VOID init_sprog(pSeqProg, pSP)
struct seqProgram *pSeqProg;
SPROG *pSP;
{
int i, nWords;
/* Copy information for state program */
pSP->numSS = pSeqProg->numSS;
pSP->numChans = pSeqProg->numChans;
pSP->numEvents = pSeqProg->numEvents;
pSP->options = pSeqProg->options;
pSP->pProgName = pSeqProg->pProgName;
pSP->exitFunc = (EXIT_FUNC)pSeqProg->exitFunc;
pSP->varSize = pSeqProg->varSize;
/* Allocate user variable area if reentrant option (+r) is set */
if ((pSP->options & OPT_REENT) != 0)
pSP->pVar = (char *)calloc(pSP->varSize, 1);
#ifdef DEBUG
logMsg("init_sprog: num SS=%d, num Chans=%d, num Events=%d, Prog Name=%s, var Size=%d\n",
pSP->numSS, pSP->numChans, pSP->numEvents, pSP->pProgName, pSP->varSize);
#endif /*DEBUG*/
/* Create a semaphore for resource locking on CA events */
pSP->caSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
if (pSP->caSemId == NULL)
{
logMsg("can't create caSemId\n", 0,0,0,0,0,0);
return;
}
pSP->task_is_deleted = FALSE;
pSP->connCount = 0;
pSP->assignCount = 0;
pSP->logFd = 0;
/* Allocate an array for event flag bits */
nWords = (pSP->numEvents + NBITS - 1) / NBITS;
if (nWords == 0)
nWords = 1;
pSP->pEvents = (bitMask *)calloc(nWords, sizeof(bitMask));
for (i = 0; i < nWords; i++)
pSP->pEvents[i] = 0;
return;
}
/*
* Initialize the state set control blocks
*/
LOCAL VOID init_sscb(pSeqProg, pSP)
struct seqProgram *pSeqProg;
SPROG *pSP;
{
SSCB *pSS;
STATE *pState;
int nss, nstates;
struct seqSS *pSeqSS;
struct seqState *pSeqState;
/* Allocate space for the SSCB structures */
pSP->pSS = pSS = (SSCB *)calloc(pSeqProg->numSS, sizeof(SSCB));
/* Copy information for each state set and state */
pSeqSS = pSeqProg->pSS;
for (nss = 0; nss < pSeqProg->numSS; nss++, pSS++, pSeqSS++)
{
/* Fill in SSCB */
pSS->pSSName = pSeqSS->pSSName;
pSS->numStates = pSeqSS->numStates;
pSS->errorState = pSeqSS->errorState;
pSS->currentState = 0; /* initial state */
pSS->nextState = 0;
pSS->prevState = 0;
pSS->taskId = 0;
pSS->sprog = pSP;
#ifdef DEBUG
logMsg("init_sscb: SS Name=%s, num States=%d, pSS=0x%x\n",
pSS->pSSName, pSS->numStates, pSS, 0,0,0);
#endif /*DEBUG*/
/* Create a binary semaphore for synchronizing events in a SS */
pSS->syncSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
if (pSS->syncSemId == NULL)
{
logMsg("can't create syncSemId\n", 0,0,0,0,0,0);
return;
}
/* Create a binary semaphore for synchronous pvGet() (-a) */
if ((pSP->options & OPT_ASYNC) == 0)
{
pSS->getSemId =
semBCreate(SEM_Q_FIFO, SEM_FULL);
if (pSS->getSemId == NULL)
{
logMsg("can't create getSemId\n", 0,0,0,0,0,0);
return;
}
}
/* Allocate & fill in state blocks */
pSS->pStates = pState = (STATE *)calloc(pSS->numStates, sizeof(STATE));
pSeqState = pSeqSS->pStates;
for (nstates = 0; nstates < pSeqSS->numStates;
nstates++, pState++, pSeqState++)
{
pState->pStateName = pSeqState->pStateName;
pState->actionFunc = (ACTION_FUNC)pSeqState->actionFunc;
pState->eventFunc = (EVENT_FUNC)pSeqState->eventFunc;
pState->delayFunc = (DELAY_FUNC)pSeqState->delayFunc;
pState->pEventMask = pSeqState->pEventMask;
#ifdef DEBUG
logMsg("init_sscb: State Name=%s, Event Mask=0x%x\n",
pState->pStateName, *pState->pEventMask, 0,0,0,0);
#endif /*DEBUG*/
}
}
#ifdef DEBUG
logMsg("init_sscb: numSS=%d\n", pSP->numSS, 0,0,0,0,0);
#endif /*DEBUG*/
return;
}
/*
* init_chan--Build the database channel structures.
* Note: Actual PV name is not filled in here. */
LOCAL VOID init_chan(pSeqProg, pSP)
struct seqProgram *pSeqProg;
SPROG *pSP;
{
int nchan;
CHAN *pDB;
struct seqChan *pSeqChan;
/* Allocate space for the CHAN structures */
pSP->pChan = (CHAN *)calloc(pSP->numChans, sizeof(CHAN));
pDB = pSP->pChan;
pSeqChan = pSeqProg->pChan;
for (nchan = 0; nchan < pSP->numChans; nchan++, pDB++, pSeqChan++)
{
#ifdef DEBUG
logMsg("init_chan: pDB=0x%x\n", pDB, 0,0,0,0,0);
#endif /*DEBUG*/
pDB->sprog = pSP;
pDB->dbAsName = pSeqChan->dbAsName;
pDB->pVarName = pSeqChan->pVarName;
pDB->pVarType = pSeqChan->pVarType;
pDB->pVar = pSeqChan->pVar; /* this is an offset for +r option */
pDB->count = pSeqChan->count;
pDB->efId = pSeqChan->efId;
pDB->monFlag = pSeqChan->monFlag;
pDB->eventNum = pSeqChan->eventNum;
pDB->assigned = 0;
/* Fill in get/put database types, element size, & access offset */
selectDBtype(pSeqChan->pVarType, &pDB->getType,
&pDB->putType, &pDB->size, &pDB->dbOffset);
/* Reentrant option: Convert offset to address of the user variable. */
if ((pSP->options & OPT_REENT) != 0)
pDB->pVar += (int)pSP->pVar;
#ifdef DEBUG
logMsg(" Assigned Name=%s, VarName=%s, VarType=%s, count=%d\n",
pDB->dbAsName, pDB->pVarName, pDB->pVarType, pDB->count, 0,0);
logMsg(" size=%d, dbOffset=%d\n", pDB->size, pDB->dbOffset, 0,0,0,0);
logMsg(" efId=%d, monFlag=%d, eventNum=%d\n",
pDB->efId, pDB->monFlag, pDB->eventNum, 0,0,0);
#endif /*DEBUG*/
}
}
/*
* init_mac - initialize the macro table.
*/
LOCAL VOID init_mac(pSP)
SPROG *pSP;
{
int i;
MACRO *pMac;
pSP->pMacros = pMac = (MACRO *)calloc(MAX_MACROS, sizeof (MACRO));
#ifdef DEBUG
logMsg("init_mac: pMac=0x%x\n", pMac, 0,0,0,0,0);
#endif /*DEBUG*/
for (i = 0 ; i < MAX_MACROS; i++, pMac++)
{
pMac->pName = NULL;
pMac->pValue = NULL;
}
}
/*
* Evaluate channel names by macro substitution.
*/
#define MACRO_STR_LEN (MAX_STRING_SIZE+1)
LOCAL VOID seqChanNameEval(pSP)
SPROG *pSP;
{
CHAN *pDB;
int i;
pDB = pSP->pChan;
for (i = 0; i < pSP->numChans; i++, pDB++)
{
pDB->dbName = calloc(1, MACRO_STR_LEN);
seqMacEval(pDB->dbAsName, pDB->dbName, MACRO_STR_LEN, pSP->pMacros);
#ifdef DEBUG
logMsg("seqChanNameEval: \"%s\" evaluated to \"%s\"\n",
pDB->dbAsName, pDB->dbName, 0,0,0,0);
#endif /*DEBUG*/
}
}
/*
* selectDBtype -- returns types for DB put/getm element size, and db access
* offset based on user variable type.
* Mapping is determined by the following typeMap[] array.
* DBR_TIME_* types for gets/monitors returns status and time stamp.
* Note that type "int" is mapped into DBR_LONG, because DBR_INT is actually
* 16 bits as defined in the database. This could cause future problems
* if the cpu architecture or compiler doesn't make this same assumption!
*/
LOCAL struct typeMap {
char *pTypeStr;
short putType;
short getType;
short size;
short offset;
} typeMap[] = {
{
"char", DBR_CHAR, DBR_TIME_CHAR,
sizeof (char), OFFSET(struct dbr_time_char, value)
},
{
"short", DBR_SHORT, DBR_TIME_SHORT,
sizeof (short), OFFSET(struct dbr_time_short, value)
},
{
"int", DBR_LONG, DBR_TIME_LONG,
sizeof (long), OFFSET(struct dbr_time_long, value)
},
{
"long", DBR_LONG, DBR_TIME_LONG,
sizeof (long), OFFSET(struct dbr_time_long, value)
},
{
"unsigned char", DBR_CHAR, DBR_TIME_CHAR,
sizeof (char), OFFSET(struct dbr_time_char, value)
},
{
"unsigned short", DBR_SHORT, DBR_TIME_SHORT,
sizeof (short), OFFSET(struct dbr_time_short, value)
},
{
"unsigned int", DBR_LONG, DBR_TIME_LONG,
sizeof (long), OFFSET(struct dbr_time_long, value)
},
{
"unsigned long", DBR_LONG, DBR_TIME_LONG,
sizeof (long), OFFSET(struct dbr_time_long, value)
},
{
"float", DBR_FLOAT, DBR_TIME_FLOAT,
sizeof (float), OFFSET(struct dbr_time_float, value)
},
{
"double", DBR_DOUBLE, DBR_TIME_DOUBLE,
sizeof (double), OFFSET(struct dbr_time_double, value)
},
{
"string", DBR_STRING, DBR_TIME_STRING,
MAX_STRING_SIZE, OFFSET(struct dbr_time_string, value[0])
},
{
0, 0, 0, 0, 0
}
};
LOCAL VOID selectDBtype(pUserType, pGetType, pPutType, pSize, pOffset)
char *pUserType;
short *pGetType, *pPutType, *pSize, *pOffset;
{
struct typeMap *pMap;
for (pMap = &typeMap[0]; *pMap->pTypeStr != 0; pMap++)
{
if (strcmp(pUserType, pMap->pTypeStr) == 0)
{
*pGetType = pMap->getType;
*pPutType = pMap->putType;
*pSize = pMap->size;
*pOffset = pMap->offset;
return;
}
}
*pGetType = *pPutType = *pSize = *pOffset = 0; /* this shouldn't happen */
return;
}
/*
* seq_logInit() - Initialize logging.
* If "logfile" is not specified, then we log to standard output.
*/
LOCAL VOID seq_logInit(pSP)
SPROG *pSP;
{
char *pValue;
int fd;
/* Create a logging resource locking semaphore */
pSP->logSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
if (pSP->logSemId == NULL)
{
logMsg("can't create logSemId\n", 0,0,0,0,0,0);
return;
}
pSP->logFd = ioGlobalStdGet(1); /* default fd is std out */
/* Check for logfile spec. */
pValue = seqMacValGet(pSP->pMacros, "logfile");
if (pValue != NULL && strlen(pValue) > 0)
{ /* Create & open a new log file for write only */
remove(pValue); /* remove the file if it exists */
fd = open(pValue, O_CREAT | O_WRONLY, 0664);
if (fd != ERROR)
pSP->logFd = fd;
printf("logfile=%s, fd=%d\n", pValue, fd);
}
}
/*
* seq_log
* Log a message to the console or a file with task name, date, & time of day.
* The format looks like "mytask 12/13/93 10:07:43: Hello world!".
*/
#include "tsDefs.h"
#define LOG_BFR_SIZE 200
STATUS seq_log(pSP, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
SPROG *pSP;
char *fmt; /* format string */
int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
{
int fd, count, status;
TS_STAMP timeStamp;
char logBfr[LOG_BFR_SIZE], *pBfr;
pBfr = logBfr;
/* Enter taskname */
sprintf(pBfr, "%s ", taskName(taskIdSelf()) );
pBfr += strlen(pBfr);
/* Get time of day */
tsLocalTime(&timeStamp); /* time stamp format */
/* Convert to text format: "mm/dd/yy hh:mm:ss.nano-sec" */
tsStampToText(&timeStamp, TS_TEXT_MMDDYY, pBfr);
/* Truncate the ".nano-sec" part */
if (pBfr[2] == '/') /* valid t-s? */
pBfr += 17;
/* Insert ": " */
*pBfr++ = ':';
*pBfr++ = ' ';
/* Append the user's msg to the buffer */
sprintf(pBfr, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
pBfr += strlen(pBfr);
/* Write the msg */
semTake(pSP->logSemId, WAIT_FOREVER); /* lock it */
fd = pSP->logFd;
count = pBfr - logBfr + 1;
status = write(fd, logBfr, count);
semGive(pSP->logSemId);
if (status != count)
{
logMsg("Log file error, fd=%d, error no.= %d = \"%s\"\n",
fd, errnoGet(), (int) strerror(errnoGet()),0,0,0);
return ERROR;
}
/* If this is an NSF file flush the buffer */
if (fd != ioGlobalStdGet(1) )
{
ioctl(fd, FIOSYNC, 0);
}
return OK;
}
/*
* seq_seqLog() - State program interface to seq_log().
* Does not require ptr to state program block.
*/
long seq_seqLog(ssId, fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8)
SS_ID ssId;
char *fmt; /* format string */
int arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
{
SPROG *pSP;
pSP = ((SSCB *)ssId)->sprog;
return seq_log(pSP, fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8);
}
-198
View File
@@ -1,198 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1991, The Regents of the University of California.
Los Alamos National Laboratory
seq_prog.c,v 1.2 1995/06/27 15:26:00 wright Exp
DESCRIPTION: Seq_prog.c: state program list management functions.
All active state programs are inserted into the list when created
and removed from the list when deleted.
ENVIRONMENT: VxWorks
HISTORY:
09dec91,ajk original
29apr92,ajk Added mutual exclusion locks
17Jul92,rcz Changed semBCreate call for V5 vxWorks, maybe should be semMCreate ???
***************************************************************************/
/*#define DEBUG*/
#define ANSI
#include "seq.h"
#include "lstLib.h"
LOCAL SEM_ID seqProgListSemId;
LOCAL int seqProgListInited = FALSE;
LOCAL LIST seqProgList;
LOCAL VOID seqProgListInit();
typedef struct prog_node
{
NODE node;
SPROG *pSP;
} PROG_NODE;
#define seqListFirst(pList) (PROG_NODE *)lstFirst((LIST *)pList)
#define seqListNext(pNode) (PROG_NODE *)lstNext((NODE *)pNode)
/*
* seqFindProg() - find a program in the state program list from task id.
*/
SPROG *seqFindProg(taskId)
long taskId;
{
PROG_NODE *pNode;
SPROG *pSP;
SSCB *pSS;
int n;
if (!seqProgListInited || taskId == 0)
return NULL;
semTake(seqProgListSemId, WAIT_FOREVER);
for (pNode = seqListFirst(&seqProgList); pNode != NULL;
pNode = seqListNext(pNode) )
{
pSP = pNode->pSP;
if (pSP->taskId == taskId)
{
semGive(seqProgListSemId);
return pSP;
}
pSS = pSP->pSS;
for (n = 0; n < pSP->numSS; n++, pSS++)
{
if (pSS->taskId == taskId)
{
semGive(seqProgListSemId);
return pSP;
}
}
}
semGive(seqProgListSemId);
return NULL; /* not in list */
}
/*
* seqTraverseProg() - travers programs in the state program list and
* call the specified routine or function. Passes one parameter of
* pointer size.
*/
STATUS seqTraverseProg(pFunc, param)
VOID (*pFunc)(); /* function to call */
VOID *param; /* any parameter */
{
PROG_NODE *pNode;
SPROG *pSP;
if (!seqProgListInited)
return ERROR;
semTake(seqProgListSemId, WAIT_FOREVER);
for (pNode = seqListFirst(&seqProgList); pNode != NULL;
pNode = seqListNext(pNode) )
{
pSP = pNode->pSP;
pFunc(pSP, param);
}
semGive(seqProgListSemId);
return OK;
}
/*
* seqAddProg() - add a program to the state program list.
* Returns ERROR if program is already in list, else TRUE.
*/
STATUS seqAddProg(pSP)
SPROG *pSP;
{
PROG_NODE *pNode;
if (!seqProgListInited)
seqProgListInit(); /* Initialize list */
semTake(seqProgListSemId, WAIT_FOREVER);
for (pNode = seqListFirst(&seqProgList); pNode != NULL;
pNode = seqListNext(pNode) )
{
if (pSP == pNode->pSP)
{
semGive(seqProgListSemId);
#ifdef DEBUG
printf("Task %d already in list\n", pSP->taskId);
#endif
return ERROR; /* already in list */
}
}
/* Insert at head of list */
pNode = (PROG_NODE *)malloc(sizeof(PROG_NODE) );
if (pNode == NULL)
{
semGive(seqProgListSemId);
return ERROR;
}
pNode->pSP = pSP;
lstAdd((LIST *)&seqProgList, (NODE *)pNode);
semGive(seqProgListSemId);
#ifdef DEBUG
printf("Added task %d to list.\n", pSP->taskId);
#endif
return OK;
}
/*
*seqDelProg() - delete a program from the program list.
* Returns TRUE if deleted, else FALSE.
*/
STATUS seqDelProg(pSP)
SPROG *pSP;
{
PROG_NODE *pNode;
if (!seqProgListInited)
return ERROR;
semTake(seqProgListSemId, WAIT_FOREVER);
for (pNode = seqListFirst(&seqProgList); pNode != NULL;
pNode = seqListNext(pNode) )
{
if (pNode->pSP == pSP)
{
lstDelete((LIST *)&seqProgList, (NODE *)pNode);
semGive(seqProgListSemId);
#ifdef DEBUG
printf("Deleted task %d from list.\n", pSP->taskId);
#endif
return OK;
}
}
semGive(seqProgListSemId);
return ERROR; /* not in list */
}
/*
* seqProgListInit() - initialize the state program list.
*/
LOCAL VOID seqProgListInit()
{
/* Init linked list */
lstInit(&seqProgList);
/* Create a semaphore for mutual exclusion */
seqProgListSemId = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
semGive(seqProgListSemId);
seqProgListInited = TRUE;
}
-402
View File
@@ -1,402 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990-1994, The Regents of the University of California.
Los Alamos National Laboratory
seq_qry.c,v 1.2 1995/06/27 15:26:02 wright Exp
DESCRIPTION: Task querry & debug routines for run-time sequencer:
seqShow - prints state set info.
seqChanShow - printf channel (pv) info.
ENVIRONMENT: VxWorks
HISTORY:
25nov91,ajk Display task names(s) with id(s).
Display logfile name and file descriptor.
Moved wait_rtn() to top of loop.
09dec91,ajk Modified to used state program linked list.
Added option to display all programs when tid=0.
19dec91,ajk Allow task name as well as task id.
25feb92,ajk V5.0 accepts 0 as a valid task id: fixed it.
26feb92,ajk Fixed formatting of task/program listing.
29apr92,ajk Modified to interpret encoded options.
21may92,ajk Modified format for listing programs & tasks.
21feb93,ajk Some minor code cleanup.
01mar94,ajk Major changes to print more meaningful information.
***************************************************************************/
/*#define DEBUG 1*/
#include "seq.h"
#include "usrLib.h"
#include "tickLib.h"
#include "string.h"
/* User functions */
int seqShow(int);
int seqChanShow(int, char *);
LOCAL int wait_rtn();
LOCAL VOID printValue(char *, int, int);
LOCAL SPROG *seqQryFind(int);
LOCAL void seqShowAll();
/*
* seqShow() - Querry the sequencer for state information.
* If a non-zero task id is specified then print the information about
* the state program, otherwise print a brief summary of all state programs
*/
int seqShow(tid)
int tid;
{
SPROG *pSP;
SSCB *pSS;
STATE *pST;
int nss, status;
float time;
char file_name[100];
/* convert (possible) name to task id */
if (tid != 0)
{
tid = taskIdFigure(tid);
if (tid == ERROR)
return 0;
}
pSP = seqQryFind(tid);
if (pSP == NULL)
return 0;
/* Print info about state program */
printf("State Program: \"%s\"\n", pSP->pProgName);
printf(" initial task id=%lu=0x%lx\n",
(unsigned long) pSP->taskId, (unsigned long) pSP->taskId);
printf(" task priority=%ld\n", pSP->taskPriority);
printf(" number of state sets=%ld\n", pSP->numSS);
printf(" number of channels=%ld\n", pSP->numChans);
printf(" number of channels assigned=%ld\n", pSP->assignCount);
printf(" number of channels connected=%ld\n", pSP->connCount);
printf(" options: async=%d, debug=%d, newef=%d, reent=%d, conn=%d\n",
((pSP->options & OPT_ASYNC) != 0), ((pSP->options & OPT_DEBUG) != 0),
((pSP->options & OPT_NEWEF) != 0), ((pSP->options & OPT_REENT) != 0),
((pSP->options & OPT_CONN) != 0) );
if ((pSP->options & OPT_REENT) != 0)
printf(" user variables: address=%lu=0x%lx, length=%ld=0x%lx bytes\n",
(unsigned long)pSP->pVar, (unsigned long)pSP->pVar,
pSP->varSize, pSP->varSize);
printf(" log file fd=%ld\n", pSP->logFd);
status = ioctl(pSP->logFd, FIOGETNAME, (int)file_name);
if (status != ERROR)
printf(" log file name=\"%s\"\n", file_name);
printf("\n");
/* Print state set info */
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
{
printf(" State Set: \"%s\"\n", pSS->pSSName);
printf(" task name=%s; ", taskName(pSS->taskId));
printf(" task id=%lu=0x%lx\n",
(unsigned long) pSS->taskId, (unsigned long) pSS->taskId);
pST = pSS->pStates;
printf(" First state = \"%s\"\n", pST->pStateName);
pST = pSS->pStates + pSS->currentState;
printf(" Current state = \"%s\"\n", pST->pStateName);
pST = pSS->pStates + pSS->prevState;
printf(" Previous state = \"%s\"\n", pST->pStateName);
time = (tickGet() - pSS->timeEntered)/60.0;
printf("\tElapsed time since state was entered = %.1f seconds)\n",
time);
#ifdef DEBUG
printf(" Queued time delays:\n");
for (n = 0; n < pSS->numDelays; n++)
{
printf("\tdelay[%2d]=%d", n, pSS->delay[n]);
if (pSS->delayExpired[n])
printf(" - expired");
printf("\n");
}
#endif /*DEBUG*/
printf("\n");
}
return 0;
}
/*
* seqChanShow() - Show channel information for a state program.
*/
int seqChanShow(tid, pStr)
int tid; /* task id or name */
char *pStr; /* optional pattern matching string */
{
SPROG *pSP;
CHAN *pDB;
int nch, n;
char tsBfr[50], connQual;
int match, showAll;
/* convert (possible) name to task id */
if (tid != 0)
{
tid = taskIdFigure(tid);
if (tid == ERROR)
return 0;
}
pSP = seqQryFind(tid);
if (tid == NULL)
return 0;
printf("State Program: \"%s\"\n", pSP->pProgName);
printf("Number of channels=%ld\n", pSP->numChans);
if (pStr != NULL)
{
connQual = pStr[0];
/* Check for channel connect qualifier */
if ((connQual == '+') || (connQual == '-'))
{
pStr += 1;
}
}
else
connQual = 0;
pDB = pSP->pChan;
for (nch = 0; nch < pSP->numChans; )
{
if (pStr != NULL)
{
/* Check for channel connect qualifier */
if (connQual == '+')
showAll = pDB->connected; /* TRUE if connected */
else if (connQual == '-')
showAll = !pDB->connected; /* TRUE if NOT connected */
else
showAll = TRUE; /* Always TRUE */
/* Check for pattern match if specified */
match = (pStr[0] == 0) || (strstr(pDB->dbName, pStr) != NULL);
if (!(match && showAll))
{
pDB += 1;
nch += 1;
continue; /* skip this channel */
}
}
printf("\n#%d of %ld:\n", nch+1, pSP->numChans);
printf("Channel name: \"%s\"\n", pDB->dbName);
printf(" Unexpanded (assigned) name: \"%s\"\n", pDB->dbAsName);
printf(" Variable name: \"%s\"\n", pDB->pVarName);
printf(" address = %lu = 0x%lx\n",
(unsigned long)pDB->pVar, (unsigned long)pDB->pVar);
printf(" type = %s\n", pDB->pVarType);
printf(" count = %ld\n", pDB->count);
printValue(pDB->pVar, pDB->putType, pDB->count);
printf(" Monitor flag=%d\n", pDB->monFlag);
if (pDB->monitored)
printf(" Monitored\n");
else
printf(" Not monitored\n");
if (pDB->assigned)
printf(" Assigned\n");
else
printf(" Not assigned\n");
if(pDB->connected)
printf(" Connected\n");
else
printf(" Not connected\n");
if(pDB->getComplete)
printf(" Last get completed\n");
else
printf(" Get not completed or no get issued\n");
printf(" Status=%d\n", pDB->status);
printf(" Severity=%d\n", pDB->severity);
/* Print time stamp in text format: "mm/dd/yy hh:mm:ss.nano-sec" */
tsStampToText(&pDB->timeStamp, TS_TEXT_MMDDYY, tsBfr);
if (tsBfr[2] == '/') /* valid t-s? */
printf(" Time stamp = %s\n", tsBfr);
n = wait_rtn();
if (n == 0)
return 0;
nch += n;
if (nch < 0)
nch = 0;
pDB = pSP->pChan + nch;
}
return 0;
}
/* Read from console until a RETURN is detected */
LOCAL int wait_rtn()
{
char bfr[10];
int i, n;
printf("Next? (+/- skip count)\n");
for (i = 0; i < 10; i++)
{
read(STD_IN, &bfr[i], 1);
if (bfr[i] == '\n')
break;
}
bfr[i] = 0;
if (bfr[0] == 'q')
return 0; /* quit */
n = atoi(bfr);
if (n == 0)
n = 1;
return n;
}
/* Print the current internal value of a database channel */
LOCAL VOID printValue(pVal, type, count)
char *pVal;
int count, type;
{
int i;
char *c;
short *s;
long *l;
float *f;
double *d;
if (count > 5)
count = 5;
printf(" Value =");
for (i = 0; i < count; i++)
{
switch (type)
{
case DBR_STRING:
c = (char *)pVal;
for (i = 0; i < count; i++, c += MAX_STRING_SIZE)
{
printf(" %s", c);
}
break;
case DBR_CHAR:
c = (char *)pVal;
for (i = 0; i < count; i++, c++)
{
printf(" %d", *c);
}
break;
case DBR_SHORT:
s = (short *)pVal;
for (i = 0; i < count; i++, s++)
{
printf(" %d", *s);
}
break;
case DBR_LONG:
l = (long *)pVal;
for (i = 0; i < count; i++, l++)
{
printf(" %ld", *l);
}
break;
case DBR_FLOAT:
f = (float *)pVal;
for (i = 0; i < count; i++, f++)
{
printf(" %g", *f);
}
break;
case DBR_DOUBLE:
d = (double *)pVal;
for (i = 0; i < count; i++, d++)
{
printf(" %g", *d);
}
break;
}
}
printf("\n");
}
/* Find a state program associated with a given task id */
LOCAL SPROG *seqQryFind(tid)
int tid;
{
SPROG *pSP;
extern SPROG *seqFindProg();
if (tid == 0)
{
seqShowAll();
return NULL;
}
/* Find a state program that has this task id */
pSP = seqFindProg(tid);
if (pSP == NULL)
{
printf("No state program exists for task id %d\n", tid);
return NULL;
}
return pSP;
}
LOCAL int seqProgCount;
/* This routine is called by seqTraverseProg() for seqShowAll() */
LOCAL void seqShowSP(pSP)
SPROG *pSP;
{
SSCB *pSS;
int nss;
char *progName, *ptaskName;;
if (seqProgCount++ == 0)
printf("Program Name Task ID Task Name SS Name\n\n");
progName = pSP->pProgName;
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
{
if (pSS->taskId == 0)
ptaskName = "(no task)";
else
ptaskName = taskName(pSS->taskId);
printf("%-16s %-10lu %-16s %-16s\n",
progName, (unsigned long) pSS->taskId,
ptaskName, pSS->pSSName );
progName = "";
}
printf("\n");
}
/* The seqTraverseProg function is in seq_prog.c */
STATUS seqTraverseProg(VOID (*pFunc)(), VOID *param);
/* Print a brief summary of all state programs */
LOCAL void seqShowAll()
{
seqProgCount = 0;
seqTraverseProg(seqShowSP, 0);
if (seqProgCount == 0)
printf("No active state programs\n");
return;
}
-573
View File
@@ -1,573 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990-1994
The Regents of the University of California and
the University of Chicago.
Los Alamos National Laboratory
seq_task.c,v 1.3 1995/10/19 16:30:18 wright Exp
DESCRIPTION: Seq_tasks.c: Task creation and control for sequencer
state sets.
ENVIRONMENT: VxWorks
HISTORY
04dec91,ajk Implemented linked list of state programs, eliminating task
variables.
11dec91,ajk Made cosmetic changes and cleaned up comments.
19dec91,ajk Changed algoritm in seq_getTimeout().
29apr92,ajk Implemented new event flag mode.
30apr92,ajk Periodically call ca_pend_event() to detect connection failures.
21may92,ajk In sprog_delete() wait for loggin semaphore before suspending tasks.
Some minor changes in the way semaphores are deleted.
18feb92,ajk Changed to allow sharing of single CA task by all state programs.
Added seqAuxTask() and removed ca_pend_event() from ss_entry().
09aug93,ajk Added calls to taskwdInsert() & taskwdRemove().
24nov93,ajk Added support for assigning array elements to db channels.
24nov93,ajk Changed implementation of event bits to support unlimited channels
20may94,ajk Changed sprog_delete() to spawn a separate cleanup task.
19oct95,ajk/rmw Fixed bug which kept events from being cleared in old eventflag mode
20jul95,ajk Add user-specified task priority to taskSpwan().
***************************************************************************/
/*#define DEBUG*/
#include <string.h>
#define ANSI
#include "seqCom.h"
#include "seq.h"
#include "taskwd.h"
#include "logLib.h"
#include "tickLib.h"
#include "taskVarLib.h"
/* Function declarations */
LOCAL VOID seq_waitConnect(SPROG *pSP, SSCB *pSS);
LOCAL VOID ss_task_init(SPROG *, SSCB *);
LOCAL VOID seq_clearDelay(SSCB *);
LOCAL int seq_getTimeout(SSCB *);
LOCAL long seq_cleanup(int tid, SPROG *pSP, SEM_ID cleanupSem);
#define TASK_NAME_SIZE 10
STATUS seqAddProg(SPROG *pSP);
long seq_connect(SPROG *pSP);
long seq_disconnect(SPROG *pSP);
/*
* sequencer() - Sequencer main task entry point.
*/
long sequencer (pSP, stack_size, pTaskName)
SPROG *pSP; /* ptr to original (global) state program table */
long stack_size; /* stack size */
char *pTaskName; /* Parent task name */
{
SSCB *pSS;
int nss, task_id;
char task_name[TASK_NAME_SIZE+10];
extern VOID ss_entry();
extern int seqAuxTaskId;
pSP->taskId = taskIdSelf(); /* my task id */
pSS = pSP->pSS;
pSS->taskId = pSP->taskId;
/* Add the program to the state program list */
seqAddProg(pSP);
/* Import Channel Access context from the auxillary seq. task */
ca_import(seqAuxTaskId);
/* Initiate connect & monitor requests to database channels. */
seq_connect(pSP);
/* Additional state set task names are derived from the first ss */
if (strlen(pTaskName) > TASK_NAME_SIZE)
pTaskName[TASK_NAME_SIZE] = 0;
/* Create each additional state set task */
for (nss = 1, pSS = pSP->pSS + 1; nss < pSP->numSS; nss++, pSS++)
{
/* Form task name from program name + state set number */
sprintf(task_name, "%s_%d", pTaskName, nss);
/* Spawn the task */
task_id = taskSpawn(
task_name, /* task name */
pSP->taskPriority, /* priority */
SPAWN_OPTIONS, /* task options */
stack_size, /* stack size */
(FUNCPTR)ss_entry, /* entry point */
(int)pSP, (int)pSS, 0,0,0,0,0,0,0,0); /* pass 2 parameters */
seq_log(pSP, "Spawning task %d: \"%s\"\n", task_id, task_name);
}
/* First state set jumps directly to entry point */
ss_entry(pSP, pSP->pSS);
return 0;
}
/*
* ss_entry() - Task entry point for all state sets.
* Provides the main loop for state set processing.
*/
VOID ss_entry(pSP, pSS)
SPROG *pSP;
SSCB *pSS;
{
BOOL ev_trig;
STATE *pST, *pStNext;
long delay;
char *pVar;
int nWords;
SS_ID ssId;
/* Initialize all ss tasks */
ss_task_init(pSP, pSS);
/* If "+c" option, wait for all channels to connect */
if ((pSP->options & OPT_CONN) != 0)
seq_waitConnect(pSP, pSS);
/* Initilaize state set to enter the first state */
pST = pSS->pStates;
pSS->currentState = 0;
/* Use the event mask for this state */
pSS->pMask = (pST->pEventMask);
nWords = (pSP->numEvents + NBITS - 1) / NBITS;
/* Local ptr to user variables (for reentrant code only) */
pVar = pSP->pVar;
/* State set id */
ssId = (SS_ID)pSS;
/*
* ============= Main loop ==============
*/
while (1)
{
seq_clearDelay(pSS); /* Clear delay list */
pST->delayFunc(ssId, pVar); /* Set up new delay list */
/* Setting this semaphor here guarantees that a when() is always
* executed at least once when a state is first entered. */
semGive(pSS->syncSemId);
/*
* Loop until an event is triggered, i.e. when() returns TRUE
*/
do {
/* Wake up on CA event, event flag, or expired time delay */
delay = seq_getTimeout(pSS); /* min. delay from list */
if (delay > 0)
semTake(pSS->syncSemId, delay);
/* Call the event function to check for an event trigger.
* The statement inside the when() statement is executed.
* Note, we lock out CA events while doing this.
*/
semTake(pSP->caSemId, WAIT_FOREVER);
ev_trig = pST->eventFunc(ssId, pVar,
&pSS->transNum, &pSS->nextState); /* check events */
/* Clear all event flags (old ef mode only) */
if ( ev_trig && ((pSP->options & OPT_NEWEF) == 0) )
{ /* Clear all event flags (old mode only) */
register int i;
for (i = 0; i < nWords; i++)
pSP->pEvents[i] = pSP->pEvents[i] & !pSS->pMask[i];
}
semGive(pSP->caSemId);
} while (!ev_trig);
/*
* An event triggered:
* execute the action statements and enter the new state.
*/
/* Change event mask ptr for next state */
pStNext = pSS->pStates + pSS->nextState;
pSS->pMask = (pStNext->pEventMask);
/* Execute the action for this event */
pST->actionFunc(ssId, pVar, pSS->transNum);
/* Flush any outstanding DB requests */
ca_flush_io();
/* Change to next state */
pSS->prevState = pSS->currentState;
pSS->currentState = pSS->nextState;
pST = pSS->pStates + pSS->currentState;
}
}
/* Initialize state-set tasks */
LOCAL VOID ss_task_init(pSP, pSS)
SPROG *pSP;
SSCB *pSS;
{
extern int seqAuxTaskId;
/* Get this task's id */
pSS->taskId = taskIdSelf();
/* Import Channel Access context from the auxillary seq. task */
if (pSP->taskId != pSS->taskId)
ca_import(seqAuxTaskId);
/* Register this task with the EPICS watchdog (no callback function) */
taskwdInsert(pSS->taskId, (VOIDFUNCPTR)0, (VOID *)0);
return;
}
/* Wait for all channels to connect */
LOCAL VOID seq_waitConnect(SPROG *pSP, SSCB *pSS)
{
STATUS status;
long delay;
delay = 600; /* 10, 20, 30, 40, 40,... sec */
while (pSP->connCount < pSP->assignCount)
{
status = semTake(pSS->syncSemId, delay);
if ((status != OK) && (pSP-> taskId == pSS->taskId))
{
logMsg("%d of %d assigned channels have connected\n",
pSP->connCount, pSP->assignCount, 0,0,0,0);
}
if (delay < 2400)
delay = delay + 600;
}
}
/*
* seq_clearDelay() - clear the time delay list.
*/
LOCAL VOID seq_clearDelay(pSS)
SSCB *pSS;
{
int ndelay;
pSS->timeEntered = tickGet(); /* record time we entered this state */
for (ndelay = 0; ndelay < MAX_NDELAY; ndelay++)
{
pSS->delay[ndelay] = 0;
pSS->delayExpired[ndelay] = FALSE;
}
pSS->numDelays = 0;
return;
}
/*
* seq_getTimeout() - return time-out for pending on events.
* Returns number of tics to next expected timeout of a delay() call.
* Returns INT_MAX if no delays pending
* An "int" is returned because this is what semTake() expects
*/
LOCAL int seq_getTimeout(pSS)
SSCB *pSS;
{
int ndelay, delayMinInit;
ULONG cur, delay, delayMin, delayN;
if (pSS->numDelays == 0)
return INT_MAX;
/*
* calculate the delay since this state was entered
*/
cur = tickGet();
if (cur >= pSS->timeEntered) {
delay = cur - pSS->timeEntered;
}
else {
delay = cur + (ULONG_MAX - pSS->timeEntered);
}
delayMinInit = 0;
delayMin = ULONG_MAX;
/* Find the minimum delay among all non-expired timeouts */
for (ndelay = 0; ndelay < pSS->numDelays; ndelay++)
{
if (pSS->delayExpired[ndelay])
continue; /* skip if this delay entry already expired */
delayN = pSS->delay[ndelay];
if (delay >= delayN)
{ /* just expired */
pSS->delayExpired[ndelay] = TRUE; /* mark as expired */
return 0;
}
if (delayN<=delayMin) {
delayMinInit=1;
delayMin = delayN; /* this is the min. delay so far */
}
}
/*
* If there is no unexpired delay in the list
* then wait forever until there is a PV state
* change
*/
if (!delayMinInit) {
return INT_MAX;
}
/*
* unexpired delay _is_ in the list
*/
if (delayMin>delay) {
delay = delayMin - delay;
/*
* clip to the range of a valid delay in semTake()
*/
if (delay<INT_MAX) {
return delay;
}
else {
return INT_MAX;
}
}
else {
return 0;
}
}
/*
* Delete all state set tasks and do general clean-up.
* General procedure is to spawn a task that does the following:
* 1. Suspend all state set tasks except self.
* 2. Call the user program's exit routine.
* 3. Disconnect all channels for this state program.
* 4. Cancel the channel access context.
* 5. Delete all state set tasks except self.
* 6. Delete semaphores, close log file, and free allocated memory.
* 7. Return, causing self to be deleted.
*
* This task is run whenever ANY task in the system is deleted.
* Therefore, we have to check the task belongs to a state program.
* Note: We could do this without spawning a task, except for the condition
* when executed in the context of ExcTask. ExcTask is not spawned with
* floating point option, and fp is required to do the cleanup.
*/
long sprog_delete(tid)
int tid; /* task being deleted */
{
SPROG *pSP;
SEM_ID cleanupSem;
int status;
pSP = seqFindProg(tid);
if (pSP == NULL)
return -1; /* not a state program task */
/* Create a semaphore for cleanup task */
cleanupSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
/* Spawn the cleanup task */
taskSpawn("tSeqCleanup", SPAWN_PRIORITY-1, VX_FP_TASK, 8000,
(FUNCPTR)seq_cleanup, tid, (int)pSP, (int)cleanupSem, 0,0,0,0,0,0,0);
/* Wait for cleanup task completion */
for (;;)
{
status = semTake(cleanupSem, 600);
if (status == OK)
break;
logMsg("sprog_delete waiting for seq_cleanup\n", 0,0,0,0,0,0);
}
semDelete(cleanupSem);
return 0;
}
/* Cleanup task */
/*#define DEBUG_CLEANUP*/
STATUS seqDelProg(SPROG *pSP);
LOCAL long seq_cleanup(int tid, SPROG *pSP, SEM_ID cleanupSem)
{
int nss;
SSCB *pSS;
#ifdef DEBUG_CLEANUP
logMsg("Delete %s: pSP=%d=0x%x, tid=%d\n", pSP->pProgName, pSP, pSP, tid, 0,0);
#endif /*DEBUG_CLEANUP*/
/* Wait for log semaphore (in case a task is doing a write) */
semTake(pSP->logSemId, 600);
/* Remove tasks' watchdog & suspend all state set tasks except self */
#ifdef DEBUG_CLEANUP
logMsg(" Suspending state set tasks:\n");
#endif /*DEBUG_CLEANUP*/
pSS = pSP->pSS;
for (nss = 0; nss < pSP->numSS; nss++, pSS++)
{
if (pSS->taskId == 0)
continue;
#ifdef DEBUG_CLEANUP
logMsg(" tid=%d\n", pSS->taskId);
#endif /*DEBUG_CLEANUP*/
/* Remove the task from EPICS watchdog */
taskwdRemove(pSS->taskId);
/* Suspend the task */
if (pSS->taskId != tid)
taskSuspend(pSS->taskId);
}
/* Give back log semaphore */
semGive(pSP->logSemId);
/* Call user exit routine (only if task has run) */
if (pSP->pSS->taskId != 0)
{
#ifdef DEBUG_CLEANUP
logMsg(" Call exit function\n");
#endif /*DEBUG_CLEANUP*/
pSP->exitFunc( (SS_ID)pSP->pSS, pSP->pVar);
}
/* Disconnect all channels */
#ifdef DEBUG_CLEANUP
logMsg(" Disconnect all channels\n");
#endif /*DEBUG_CLEANUP*/
seq_disconnect(pSP);
/* Cancel the CA context for each state set task */
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
{
if (pSS->taskId == 0)
continue;
#ifdef DEBUG_CLEANUP
logMsg(" ca_import_cancel(0x%x)\n", pSS->taskId);
#endif /*DEBUG_CLEANUP*/
SEVCHK (ca_import_cancel(pSS->taskId),
"seq_cleanup:ca_import_cancel() failed")
}
/* Close the log file */
if ( (pSP->logFd > 0) && (pSP->logFd != ioGlobalStdGet(1)) )
{
#ifdef DEBUG_CLEANUP
logMsg("Closing log fd=%d\n", pSP->logFd);
#endif /*DEBUG_CLEANUP*/
close(pSP->logFd);
pSP->logFd = ioGlobalStdGet(1);
}
/* Remove the state program from the state program list */
seqDelProg(pSP);
/* Delete state set tasks (except self) & delete their semaphores */
pSS = pSP->pSS;
for (nss = 0; nss < pSP->numSS; nss++, pSS++)
{
if ( (pSS->taskId != tid) && (pSS->taskId != 0) )
{
#ifdef DEBUG_CLEANUP
logMsg(" delete ss task: tid=%d\n", pSS->taskId);
#endif /*DEBUG_CLEANUP*/
taskDelete(pSS->taskId);
}
if (pSS->syncSemId != 0)
semDelete(pSS->syncSemId);
if (pSS->getSemId != 0)
semDelete(pSS->getSemId);
}
/* Delete program-wide semaphores */
semDelete(pSP->caSemId);
semDelete(pSP->logSemId);
/* Free all allocated memory */
taskDelay(5);
seqFree(pSP);
semGive(cleanupSem);
return 0;
}
/* seqFree()--free all allocated memory */
VOID seqFree(pSP)
SPROG *pSP;
{
SSCB *pSS;
CHAN *pDB;
MACRO *pMac;
int n;
/* Free macro table entries */
for (pMac = pSP->pMacros, n = 0; n < MAX_MACROS; pMac++, n++)
{
if (pMac->pName != NULL)
free(pMac->pName);
if (pMac->pValue != NULL)
free(pMac->pValue);
}
/* Free MACRO table */
free(pSP->pMacros);
/* Free channel names */
for (pDB = pSP->pChan, n = 0; n < pSP->numChans; pDB++, n++)
{
if (pDB->dbName != NULL)
free(pDB->dbName);
}
/* Free channel structures */
free(pSP->pChan);
/* Free STATE blocks */
pSS = pSP->pSS;
free(pSS->pStates);
/* Free event words */
free(pSP->pEvents);
/* Free SSCBs */
free(pSP->pSS);
/* Free SPROG */
free(pSP);
}
/*
* Sequencer auxillary task -- loops on ca_pend_event().
*/
long seqAuxTask()
{
extern int seqAuxTaskId;
/* Register this task with the EPICS watchdog */
taskwdInsert(taskIdSelf(),(VOIDFUNCPTR)0, (VOID *)0);
/* Set up so all state program tasks will use a common CA context */
ca_task_initialize();
seqAuxTaskId = taskIdSelf(); /* must follow ca_task_initialize() */
/* This loop allows CA to check for connect/disconnect on channels */
for (;;)
{
ca_pend_event(10.0); /* returns every 10 sec. */
}
}
-389
View File
@@ -1,389 +0,0 @@
%{
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
snc.y,v 1.2 1995/06/27 15:26:07 wright Exp
ENVIRONMENT: UNIX
HISTORY:
20nov91,ajk Added new "option" statement.
08nov93,ajk Implemented additional declarations (see VC_CLASS in parse.h).
08nov93,ajk Implemented assignment of array elements to pv's.
02may93,ajk Removed "parameter" definition for functions, and added "%prec"
qualifications to some "expr" definitions.
31may94,ajk Changed method for handling global C code.
20jul95,ajk Added "unsigned" types (see UNSIGNED token).
11jul96,ajk Added character constants (CHAR_CONST).
13jan98,wfl Added "down a level" handling of compound expressions
09jun98,wfl Permitted pre-processor "#" lines between state-sets
***************************************************************************/
/* 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"
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif /* TRUE */
extern int line_num; /* input file line no. */
%}
%start state_program
%union
{
int ival;
char *pchar;
void *pval;
Expr *pexpr;
}
%token <pchar> STATE STATE_SET
%token <pchar> NUMBER NAME
%token <pchar> CHAR_CONST
%token <pchar> DEBUG_PRINT
%token PROGRAM EXIT OPTION
%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 POINTER COMMA OR AND
%token MONITOR ASSIGN TO WHEN
%token UNSIGNED CHAR SHORT INT LONG FLOAT DOUBLE STRING_DECL
%token EVFLAG SYNC
%token ASTERISK AMPERSAND
%token AUTO_INCR AUTO_DECR
%token PLUS MINUS SLASH GT GE EQ LE LT NE NOT BIT_OR BIT_AND
%token L_SHIFT R_SHIFT COMPLEMENT MODULO
%token PLUS_EQUAL MINUS_EQUAL MULT_EQUAL DIV_EQUAL AND_EQUAL OR_EQUAL
%token MODULO_EQUAL LEFT_EQUAL RIGHT_EQUAL CMPL_EQUAL
%token <pchar> STRING
%token <pchar> C_STMT
%token IF ELSE WHILE FOR BREAK
%token PP_SYMBOL CR
%type <ival> type
%type <pchar> subscript binop asgnop unop
%type <pexpr> state_set_list state_set state_list state transition_list transition
%type <pexpr> expr compound_expr assign_list bracked_expr
%type <pexpr> statement stmt_list compound_stmt if_stmt else_stmt while_stmt
%type <pexpr> for_stmt escaped_c_list
/* precidence rules for expr evaluation */
%right EQUAL COMMA
%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 state_set_list { program($3); }
| program_name definitions state_set_list global_c { program($3); }
| pp_code program_name definitions state_set_list { program($4); }
| pp_code program_name definitions state_set_list global_c{ program($4); }
| error { snc_err("state program"); }
;
program_name /* program name */
: 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
| option_stmt
| defn_c_stmt
| pp_code
| error { snc_err("definitions/declarations"); }
;
assign_stmt /* assign <var name> to <db name>; */
: ASSIGN NAME TO STRING SEMI_COLON { assign_single($2, $4); }
/* assign <var name>[<n>] to <db name>; */
| ASSIGN NAME subscript TO STRING SEMI_COLON { assign_subscr($2, $3, $5); }
/* assign <var name> to {<db name>, ... }; */
| ASSIGN NAME TO L_BRACKET assign_list R_BRACKET SEMI_COLON
{ assign_list($2, $5); }
;
assign_list /* {"<db name>", .... } */
: STRING { $$ = expression(E_STRING, $1, 0, 0); }
| assign_list COMMA STRING
{ $$ = link_expr($1, expression(E_STRING, $3, 0, 0)); }
;
monitor_stmt /* variable to be monitored; delta is optional */
: MONITOR NAME SEMI_COLON { monitor_stmt($2, NULL); }
| MONITOR NAME subscript SEMI_COLON { monitor_stmt($2, $3); }
;
subscript /* e.g. [10] */
: 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];)
* decl_stmt(type, class, name, <1-st dim>, <2-nd dim>, value) */
: type NAME SEMI_COLON
{ decl_stmt($1, VC_SIMPLE, $2, NULL, NULL, NULL); }
| type NAME EQUAL NUMBER SEMI_COLON
{ decl_stmt($1, VC_SIMPLE, $2, NULL, NULL, $4 ); }
| type NAME subscript SEMI_COLON
{ decl_stmt($1, VC_ARRAY1, $2, $3, NULL, NULL); }
| type NAME subscript subscript SEMI_COLON
{ decl_stmt($1, VC_ARRAY2, $2, $3, $4, NULL); }
| type ASTERISK NAME SEMI_COLON
{ decl_stmt($1, VC_POINTER, $3, NULL, NULL, NULL); }
| type ASTERISK NAME subscript SEMI_COLON
{ decl_stmt($1, VC_ARRAYP, $3, $4, NULL, NULL); }
;
type /* types for variables defined in SNL */
: CHAR { $$ = V_CHAR; }
| SHORT { $$ = V_SHORT; }
| INT { $$ = V_INT; }
| LONG { $$ = V_LONG; }
| UNSIGNED CHAR { $$ = V_UCHAR; }
| UNSIGNED SHORT { $$ = V_USHORT; }
| UNSIGNED INT { $$ = V_UINT; }
| UNSIGNED LONG { $$ = V_ULONG; }
| FLOAT { $$ = V_FLOAT; }
| DOUBLE { $$ = V_DOUBLE; }
| STRING_DECL { $$ = V_STRING; }
| EVFLAG { $$ = V_EVFLAG; }
;
sync_stmt /* sync <variable> <event flag> */
: SYNC NAME TO NAME SEMI_COLON { sync_stmt($2, NULL, $4); }
| SYNC NAME NAME SEMI_COLON { sync_stmt($2, NULL, $3); }
| SYNC NAME subscript TO NAME SEMI_COLON { sync_stmt($2, $3, $5); }
| SYNC NAME subscript NAME SEMI_COLON { sync_stmt($2, $3, $4); }
;
defn_c_stmt /* escaped C in definitions */
: escaped_c_list { defn_c_stmt($1); }
;
option_stmt /* option +/-<option>; e.g. option +a; */
: OPTION PLUS NAME SEMI_COLON { option_stmt($3, TRUE); }
| OPTION MINUS NAME SEMI_COLON { option_stmt($3, FALSE); }
;
state_set_list /* a program body is one or more state sets */
: state_set { $$ = $1; }
| state_set_list state_set { $$ = link_expr($1, $2); }
;
state_set /* define a state set */
: STATE_SET NAME L_BRACKET state_list R_BRACKET
{ $$ = expression(E_SS, $2, $4, 0); }
| EXIT L_BRACKET stmt_list R_BRACKET
{ exit_code($3); $$ = 0; }
| pp_code { $$ = 0; }
| error { snc_err("state set"); }
;
state_list /* define a state set body (one or more states) */
: state { $$ = $1; }
| state_list state { $$ = link_expr($1, $2); }
| error { snc_err("state set"); }
;
state /* a block that defines a single state */
: STATE NAME L_BRACKET transition_list R_BRACKET
{ $$ = expression(E_STATE, $2, $4, 0); }
| error { snc_err("state block"); }
;
transition_list /* all transitions for one state */
: transition { $$ = $1; }
| transition_list transition { $$ = link_expr($1, $2); }
| error { snc_err("transition"); }
;
transition /* define a transition ("when" statment ) */
: WHEN L_PAREN expr R_PAREN L_BRACKET stmt_list R_BRACKET STATE NAME
{ $$ = expression(E_WHEN, $9, $3, $6); }
;
expr /* general expr: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */
/* Expr *expression(int type, char *value, Expr *left, Expr *right) */
: compound_expr { $$ = expression(E_COMMA, "", $1, 0); }
| expr binop expr %prec UOP { $$ = expression(E_BINOP, $2, $1, $3); }
| expr asgnop expr { $$ = expression(E_ASGNOP, $2, $1, $3); }
| unop expr %prec UOP { $$ = expression(E_UNOP, $1, $2, 0); }
| AUTO_INCR expr %prec UOP { $$ = expression(E_PRE, "++", $2, 0); }
| AUTO_DECR expr %prec UOP { $$ = expression(E_PRE, "--", $2, 0); }
| expr AUTO_INCR %prec UOP { $$ = expression(E_POST, "++", $1, 0); }
| expr AUTO_DECR %prec UOP { $$ = expression(E_POST, "--", $1, 0); }
| NUMBER { $$ = expression(E_CONST, $1, 0, 0); }
| CHAR_CONST { $$ = expression(E_CONST, $1, 0, 0); }
| STRING { $$ = expression(E_STRING, $1, 0, 0); }
| NAME { $$ = expression(E_VAR, $1, 0, 0); }
| NAME L_PAREN expr R_PAREN { $$ = expression(E_FUNC, $1, $3, 0); }
| EXIT L_PAREN expr R_PAREN { $$ = expression(E_FUNC, "exit", $3, 0); }
| L_PAREN expr R_PAREN { $$ = expression(E_PAREN, "", $2, 0); }
| expr bracked_expr %prec SUBSCRIPT { $$ = expression(E_SUBSCR, "", $1, $2); }
| /* empty */ { $$ = 0; }
;
compound_expr
: expr COMMA expr { $$ = link_expr($1, $3); }
| compound_expr COMMA expr { $$ = link_expr($1, $3); }
;
bracked_expr /* e.g. [k-1] */
: L_SQ_BRACKET expr R_SQ_BRACKET { $$ = $2; }
;
unop /* Unary operators */
: PLUS { $$ = "+"; }
| MINUS { $$ = "-"; }
| ASTERISK { $$ = "*"; }
| AMPERSAND { $$ = "&"; }
| NOT { $$ = "!"; }
;
binop /* Binary operators */
: MINUS { $$ = "-"; }
| PLUS { $$ = "+"; }
| ASTERISK { $$ = "*"; }
| SLASH { $$ = "/"; }
| GT { $$ = ">"; }
| GE { $$ = ">="; }
| EQ { $$ = "=="; }
| NE { $$ = "!="; }
| LE { $$ = "<="; }
| LT { $$ = "<"; }
| OR { $$ = "||"; }
| AND { $$ = "&&"; }
| L_SHIFT { $$ = "<<"; }
| R_SHIFT { $$ = ">>"; }
| BIT_OR { $$ = "|"; }
| BIT_AND { $$ = "&"; }
| COMPLEMENT { $$ = "^"; }
| MODULO { $$ = "%"; }
| PERIOD { $$ = "."; } /* fudges structure elements */
| POINTER { $$ = "->"; } /* fudges ptr to structure elements */
;
asgnop /* Assignment operators */
: EQUAL { $$ = "="; }
| PLUS_EQUAL { $$ = "+="; }
| MINUS_EQUAL { $$ = "-="; }
| AND_EQUAL { $$ = "&="; }
| OR_EQUAL { $$ = "|="; }
| DIV_EQUAL { $$ = "/="; }
| MULT_EQUAL { $$ = "*="; }
| MODULO_EQUAL { $$ = "%="; }
| LEFT_EQUAL { $$ = "<<="; }
| RIGHT_EQUAL { $$ = ">>="; }
| CMPL_EQUAL { $$ = "^="; }
;
compound_stmt /* compound statement e.g. { ...; ...; ...; } */
: L_BRACKET stmt_list R_BRACKET { $$ = expression(E_CMPND, "",$2, 0); }
| error { snc_err("action statements"); }
;
stmt_list
: statement { $$ = $1; }
| stmt_list statement { $$ = link_expr($1, $2); }
| /* empty */ { $$ = 0; }
;
statement
: compound_stmt { $$ = $1; }
| expr SEMI_COLON { $$ = expression(E_STMT, "", $1, 0); }
| BREAK SEMI_COLON { $$ = expression(E_BREAK, "", 0, 0); }
| if_stmt { $$ = $1; }
| else_stmt { $$ = $1; }
| while_stmt { $$ = $1; }
| for_stmt { $$ = $1; }
| C_STMT { $$ = expression(E_TEXT, "", $1, 0); }
| pp_code { $$ = 0; }
| error { snc_err("action statement"); }
;
if_stmt
: IF L_PAREN expr R_PAREN statement { $$ = expression(E_IF, "", $3, $5); }
;
else_stmt
: ELSE statement { $$ = expression(E_ELSE, "", $2, 0); }
;
while_stmt
: WHILE L_PAREN expr R_PAREN statement { $$ = expression(E_WHILE, "", $3, $5); }
;
for_stmt
: FOR L_PAREN expr SEMI_COLON expr SEMI_COLON expr R_PAREN statement
{ $$ = expression(E_FOR, "", expression(E_X, "", $3, $5),
expression(E_X, "", $7, $9) ); }
;
pp_code /* pre-processor code (e.g. # 1 "test.st") */
: PP_SYMBOL NUMBER STRING CR { pp_code($2, $3, ""); }
| PP_SYMBOL NUMBER STRING NUMBER CR { pp_code($2, $3, $4); }
;
global_c
: escaped_c_list { global_c_stmt($1); }
;
escaped_c_list
: C_STMT { $$ = expression(E_TEXT, "", $1, 0); }
| escaped_c_list C_STMT { $$ = link_expr($1, expression(E_TEXT, "", $2, 0)); }
;
%%
#include "snc_lex.c"
static int yyparse (void);
/* yyparse() is static, so we create global access to it */
void Global_yyparse (void)
{
yyparse ();
}
-253
View File
@@ -1,253 +0,0 @@
%{
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
snc_lex.l,v 1.2 1995/06/27 15:26:09 wright Exp
ENVIRONMENT: UNIX
HISTORY:
20nov91,ajk Added OPTION token.
15jan92,ajk Fixed to allow "!" as a unary operator.
17Jul92,rcz changed warn_flag to warn_opt
17Jul92,rcz Ported ajk version from lanl
04apr93,ajk Increased STR_BFR_SIZE from 30000 to 300000
19nov93,ajk Added definitions for octal and hex numbers.
19nov93,ajk Removed optional "-" from definition of FPNUM. This was
causing problems with statements like "k-1".
27man94,ajk Implemented dynamic allocation of strings, thus eliminating
huge string buffer.
31may94,ajk Changed handling of escaped C code.
17feb95,ajk Removed includes "parse.h" & "snc.h", because this module
now gets included in snc.y.
20jul95,ajk Added unsigned types.
11jul96,ajk Added character constants
01oct98,wfl Replaced FPNUM with version from Sun lex manual ("E" support)
***************************************************************************/
/* 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 "string.h"
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/*#define DEBUG 1*/
#ifdef DEBUG
#define RETURN(param) { fprintf(stderr, "return(param)\n"); return(param); }
#else
#define RETURN(param) return(param);
#endif
#define STR_BFR_SIZE 1000
extern int line_num, c_line_num; /* input line number */
extern int warn_opt; /* compiler warning flag */
char strBfr[STR_BFR_SIZE]; /* holding place for strings */
char *pStr; /* current ptr to strBfr */
double atof();
int one_line_c_code; /* TRUE for %%; FALSE for %{...}% */
%}
/* Start conditions (SNL, C code, comment, string, pre-processor, pre-proc. string) */
%Start SNL C_CODE COMMENT STR PP PP_STR
/* FPNUM was:
FPNUM (([0-9]+)(\.[0-9]*)?)|(\.[0-9]+)
replaced 01-Oct-98 */
NAME [a-zA-Z][a-zA-Z0-9_]*
DIG [0-9]
EXP [DEde][-+]?{DIG}+
FPNUM {DIG}+({EXP})?|{DIG}+\.{DIG}*({EXP})?|{DIG}*\.{DIG}+({EXP})?
OCTAL 0[0-7]+
HEX 0x([0-9a-fA-F])+
CCONST \'.\'
%% /* Begin rules */
<C_CODE>. *pStr++ = yytext[0];
<C_CODE>\n {
*pStr++ = 0;
line_num++;
c_line_num = line_num;
yylval.pchar = strdup(strBfr);
pStr = strBfr;
if (one_line_c_code)
BEGIN SNL;
RETURN(C_STMT);
}
<C_CODE>"}%" {
*pStr++ = 0;
yylval.pchar = strdup(strBfr);
BEGIN SNL;
RETURN(C_STMT);
}
<COMMENT>\n line_num++;
<COMMENT>"*/" BEGIN SNL;
<COMMENT>. ;
<STR>"\\\"" {
*pStr++ = yytext[0];
*pStr++ = yytext[1];
}
<STR>\" {
*pStr++ = 0;
yylval.pchar = strdup(strBfr);
BEGIN SNL;
RETURN(STRING);
}
<STR>. { *pStr++ = yytext[0]; }
<STR>\n { *pStr++ = '?';
if (warn_opt)
fprintf(stderr, "Warning: newline in string, line %d\n",
line_num);
line_num++;
}
<PP>{FPNUM} { yylval.pchar = strdup(yytext);
RETURN(NUMBER);
}
<PP>\" { pStr = strBfr; BEGIN PP_STR; }
<PP>\n {
BEGIN SNL;
RETURN(CR);
}
<PP>[\t\ ]* /* no action */ ;
<PP>. {
}
<PP_STR>\" {
*pStr++ = 0;
yylval.pchar = strdup(strBfr);
BEGIN PP;
RETURN(STRING);
}
<PP_STR>. { *pStr++ = yytext[0]; }
<PP_STR>\n { *pStr++ = '?'; line_num++; }
<SNL>\n { line_num++; }
<SNL>"%{" {
pStr = strBfr;
one_line_c_code = FALSE;
c_line_num = line_num;
BEGIN C_CODE;
}
<SNL>"%%" {
pStr = strBfr;
one_line_c_code = TRUE;
c_line_num = line_num;
BEGIN C_CODE;
}
<SNL>^# {
BEGIN PP;
RETURN(PP_SYMBOL);
}
<SNL>"/*" BEGIN COMMENT;
<SNL>\" { pStr = strBfr; BEGIN STR; }
<SNL>"ss" RETURN(STATE_SET);
<SNL>"state" RETURN(STATE);
<SNL>"when" RETURN(WHEN);
<SNL>"monitor" RETURN(MONITOR);
<SNL>"assign" RETURN(ASSIGN);
<SNL>"unsigned" RETURN(UNSIGNED);
<SNL>"char" RETURN(CHAR);
<SNL>"short" RETURN(SHORT);
<SNL>"int" RETURN(INT);
<SNL>"long" RETURN(LONG);
<SNL>"float" RETURN(FLOAT);
<SNL>"double" RETURN(DOUBLE);
<SNL>"string" RETURN(STRING_DECL);
<SNL>"to" RETURN(TO);
<SNL>"program" RETURN(PROGRAM);
<SNL>"option" RETURN(OPTION);
<SNL>"debug" RETURN(DEBUG_PRINT);
<SNL>"evflag" RETURN(EVFLAG);
<SNL>"sync" RETURN(SYNC);
<SNL>"if" RETURN(IF);
<SNL>"else" RETURN(ELSE);
<SNL>"while" RETURN(WHILE);
<SNL>"for" RETURN(FOR);
<SNL>"break" RETURN(BREAK);
<SNL>"exit" RETURN(EXIT);
<SNL>"TRUE" { yylval.pchar = "1";
RETURN(NUMBER);
}
<SNL>"FALSE" {
yylval.pchar = "0";
RETURN(NUMBER);
}
<SNL>{NAME} {
yylval.pchar = strdup(yytext);
RETURN(NAME);
}
<SNL>"++" RETURN(AUTO_INCR);
<SNL>"--" RETURN(AUTO_DECR);
<SNL>"||" RETURN(OR);
<SNL>"<<=" RETURN(LEFT_EQUAL);
<SNL>">>=" RETURN(RIGHT_EQUAL);
<SNL>"&&" RETURN(AND);
<SNL>">>" RETURN(R_SHIFT);
<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(L_SHIFT);
<SNL>"<=" RETURN(LE);
<SNL>"%=" RETURN(MODULO_EQUAL);
<SNL>"^=" RETURN(CMPL_EQUAL);
<SNL>"->" RETURN(POINTER);
<SNL>"+" RETURN(PLUS);
<SNL>"-" RETURN(MINUS);
<SNL>"!" RETURN(NOT);
<SNL>"/" RETURN(SLASH);
<SNL>"<" RETURN(LT);
<SNL>">" RETURN(GT);
<SNL>"|" RETURN(BIT_OR);
<SNL>"&" RETURN(BIT_AND);
<SNL>"^" RETURN(COMPLEMENT);
<SNL>"%" RETURN(MODULO);
<SNL>"=" RETURN(EQUAL);
<SNL>"&" RETURN(AMPERSAND);
<SNL>"*" RETURN(ASTERISK);
<SNL>"{" RETURN(L_BRACKET);
<SNL>"}" RETURN(R_BRACKET);
<SNL>"[" RETURN(L_SQ_BRACKET);
<SNL>"]" RETURN(R_SQ_BRACKET);
<SNL>":" RETURN(COLON);
<SNL>";" RETURN(SEMI_COLON);
<SNL>"." RETURN(PERIOD);
<SNL>"(" RETURN(L_PAREN);
<SNL>")" RETURN(R_PAREN);
<SNL>"," RETURN(COMMA);
<SNL>{HEX} {
yylval.pchar = strdup(yytext);
RETURN(NUMBER);
}
<SNL>{OCTAL} {
yylval.pchar = strdup(yytext);
RETURN(NUMBER);
}
<SNL>{FPNUM} {
yylval.pchar = strdup(yytext);
RETURN(NUMBER);
}
<SNL>{CCONST} {
yylval.pchar = strdup(yytext);
RETURN(CHAR_CONST);
}
<SNL>[\t\ ]* /* no action */ ;
<SNL>. RETURN(BAD_CHAR);
# { /* somehow "^#" doesn't work if it's first char */
BEGIN PP;
RETURN(PP_SYMBOL)
}
.|\n { line_num = 1; BEGIN SNL; yyless(0); }
-296
View File
@@ -1,296 +0,0 @@
/**************************************************************************
GTA PROJECT AT division
Copyright, 1990, The Regents of the University of California.
Los Alamos National Laboratory
snc_main.c,v 1.2 1995/06/27 15:26:11 wright Exp
DESCRIPTION: Main program and miscellaneous routines for
State Notation Compiler.
ENVIRONMENT: UNIX
HISTORY:
20nov91,ajk Removed call to init_snc().
20nov91,ajk Removed some debug stuff.
28apr92,ajk Implemented new event flag mode.
29oct93,ajk Added 'v' (vxWorks include) option.
17may94,ajk Changed setlinebuf() to setvbuf().
17may94,ajk Removed event flag option (-e).
17feb95,ajk Changed yyparse() to Global_yyparse(), because FLEX makes
yyparse() static.
02mar95,ajk Changed bcopy () to strcpy () in 2 places.
26jun95,ajk Due to popular demand, reinstated event flag (-e) option.
***************************************************************************/
extern char *sncVersion; /* snc version and date created */
#include <stdio.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
/* SNC Globals: */
char in_file[200]; /* input file name */
char out_file[200]; /* output file name */
char *src_file; /* ptr to (effective) source file name */
int line_num; /* current src file line number */
int c_line_num; /* line number for beginning of C code */
/* Compile & run-time options: */
int async_opt = FALSE; /* do pvGet() asynchronously */
int conn_opt = TRUE; /* wait for all connections to complete */
int debug_opt = FALSE; /* run-time debug */
int newef_opt = TRUE; /* new event flag mode */
int line_opt = TRUE; /* line numbering */
int reent_opt = FALSE; /* reentrant at run-time */
int warn_opt = TRUE; /* compiler warnings */
int vx_opt = TRUE; /* include vxWorks def's */
/*+************************************************************************
* 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();
/* 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);
}
/* Redirect output stream to specified file */
outfp = freopen(out_file, "w", stdout);
if (outfp == NULL)
{
perror(out_file);
exit(1);
}
/* src_file is used to mark the output file for snc & cc errors */
src_file = in_file;
/* Use line buffered output */
setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);
printf("/* %s: %s */\n\n", sncVersion, in_file);
/* Call the SNC parser */
Global_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[];
{
char *s;
if (argc < 2)
{
fprintf(stderr, "%s\n", sncVersion);
fprintf(stderr, "usage: snc <options> <infile>\n");
fprintf(stderr, "options:\n");
fprintf(stderr, " +a - do async. pvGet\n");
fprintf(stderr, " -c - don't wait for all connects\n");
fprintf(stderr, " +d - turn on debug run-time option\n");
fprintf(stderr, " -e - don't use new event flag mode\n");
fprintf(stderr, " -l - supress line numbering\n");
fprintf(stderr, " +r - make reentrant at run-time\n");
fprintf(stderr, " -w - supress compiler warnings\n");
fprintf(stderr, " -v - don't include VxWorks definitions\n");
fprintf(stderr, "example:\n snc +a -c vacuum.st\n");
exit(1);
}
for (argc--, argv++; argc > 0; argc--, argv++)
{
s = *argv;
if (*s == '+' || *s == '-')
get_options(s);
else
get_in_file(s);
}
}
get_options(s)
char *s;
{
int opt_val;
if (*s == '+')
opt_val = TRUE;
else
opt_val = FALSE;
switch (s[1])
{
case 'a':
async_opt = opt_val;
break;
case 'c':
conn_opt = opt_val;
break;
case 'd':
debug_opt = opt_val;
break;
case 'e':
newef_opt = opt_val;
break;
case 'l':
line_opt = opt_val;
break;
case 'r':
reent_opt = opt_val;
break;
case 'w':
warn_opt = opt_val;
break;
case 'v':
vx_opt = opt_val;
break;
default:
fprintf(stderr, "Unknown option: \"%s\"\n", s);
break;
}
}
get_in_file (s)
char *s;
{
int ls;
ls = strlen (s);
strcpy (in_file, s);
strcpy (out_file, s);
if ( strcmp (&in_file[ls-3], ".st") == 0 )
{
out_file[ls-2] = 'c';
out_file[ls-1] = 0;
}
else if (in_file[ls-2] == '.')
{ /* change suffix to 'c' */
out_file[ls -1] = 'c';
}
else
{ /* append ".c" */
out_file[ls] = '.';
out_file[ls+1] = 'c';
out_file[ls+2] = 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)
char *err_txt;
{
fprintf(stderr, " %s\n", err_txt);
exit(1);
}
/*+************************************************************************
* 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 (%s)\n", err, line_num, src_file);
return;
}
/*+************************************************************************
* NAME: print_line_num
*
* CALLING SEQUENCE
* type argument I/O description
* ---------------------------------------------------
* int line_num I current line number
* char src_file I effective source file
*
* 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, src_file)
int line_num;
char *src_file;
{
if (line_opt)
printf("# line %d \"%s\"\n", line_num, src_file);
return;
}