Sequencer V1.9.0(3.12.1) form lanl.
This commit is contained in:
@@ -1,10 +1,16 @@
|
||||
#
|
||||
# $Id$
|
||||
# Makefile,v 1.2 1995/06/27 15:25:35 wright Exp
|
||||
#
|
||||
# Lowest Level Directroy Makefile
|
||||
# by Janet Anderson
|
||||
#
|
||||
# $Log$
|
||||
# Makefile,v
|
||||
# Revision 1.2 1995/06/27 15:25:35 wright
|
||||
# Brought over Andy's sequencer 1.9 files, compiled and created new seq and snc.
|
||||
#
|
||||
# Revision 1.1 1994/09/07 19:26:37 jba
|
||||
# New file
|
||||
#
|
||||
#
|
||||
|
||||
EPICS=../../..
|
||||
|
||||
@@ -11,11 +11,11 @@ YACC = $(EYACC)
|
||||
USR_LDLIBS = -ll
|
||||
YACCOPT = -d -v
|
||||
|
||||
SRCS.c = ../parse.c ../phase2.c ../gen_ss_code.c \
|
||||
../gen_tables.c sncVersion.c snc.c
|
||||
SRCS.c = ../snc_main.c ../parse.c ../phase2.c ../gen_ss_code.c \
|
||||
../gen_tables.c sncVersion.c snc.c
|
||||
|
||||
OBJS = parse.o phase2.o gen_ss_code.o \
|
||||
gen_tables.o sncVersion.o snc.o
|
||||
OBJS = snc_main.o parse.o phase2.o gen_ss_code.o \
|
||||
gen_tables.o sncVersion.o snc.o
|
||||
|
||||
PROD = snc
|
||||
|
||||
@@ -24,7 +24,7 @@ include $(EPICS)/config/RULES.Unix
|
||||
#
|
||||
# The generated lex file includes snc.h
|
||||
#
|
||||
snc_lex.c: snc.h
|
||||
snc_lex.c: snc.h ../snc_lex.l
|
||||
|
||||
snc.o: snc_lex.c
|
||||
|
||||
|
||||
@@ -6,19 +6,23 @@ USR_CFLAGS =
|
||||
|
||||
SRCS.c = \
|
||||
../seq_main.c ../seq_ca.c ../seq_qry.c ../seq_task.c \
|
||||
../seq_mac.c ../seq_prog.c
|
||||
../seq_mac.c ../seq_prog.c ../seq_if.c
|
||||
|
||||
LIBOBJS = \
|
||||
OBJS = \
|
||||
seq_main.o seq_ca.o seq_qry.o seq_task.o \
|
||||
seq_mac.o seq_prog.o seqVersion.o
|
||||
seq_mac.o seq_prog.o seq_if.o seqVersion.o
|
||||
|
||||
LIBNAME = seq
|
||||
PROD = seq
|
||||
|
||||
include $(EPICS)/config/RULES.Vx
|
||||
|
||||
clean::
|
||||
@$(RM) seqVersion.c
|
||||
|
||||
seq: $(OBJS)
|
||||
$(RM) $@
|
||||
$(LINK.c) $@ $(OBJS) $(LDLIBS)
|
||||
|
||||
seqVersion.c: ../Version
|
||||
$(RM) seqVersion.c
|
||||
sh ../makeSeqVersion ../Version > seqVersion.c
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
1.8.3
|
||||
1.9.0(3.12.1)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# epics/release $Id$
|
||||
# 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
|
||||
#
|
||||
|
||||
@@ -2,19 +2,20 @@
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
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.
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include "cadef.h"
|
||||
#include <dbDefs.h>
|
||||
#include <seqU.h>
|
||||
#include <dbDefs.h>
|
||||
#include <seqCom.h>
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: gen_ss_code
|
||||
@@ -29,6 +30,7 @@
|
||||
*
|
||||
* NOTES: All inputs are external globals.
|
||||
*-*************************************************************************/
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#define EVENT_STMT 1
|
||||
#define ACTION_STMT 2
|
||||
@@ -50,7 +52,7 @@ gen_ss_code()
|
||||
printf("\f/* Code for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->value, ssp->value);
|
||||
|
||||
/* Generate delay processing function */
|
||||
/* Generate function to set up for delay processing */
|
||||
gen_delay_func(sp, ssp);
|
||||
|
||||
/* Generate event processing function */
|
||||
@@ -64,9 +66,64 @@ gen_ss_code()
|
||||
/* 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 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:
|
||||
|
||||
/* Generate action processing functions:
|
||||
Each state has one action routine. It's name is derived from the
|
||||
state set name and the state name.
|
||||
*/
|
||||
@@ -78,17 +135,20 @@ Expr *ssp; /* Parent state set */
|
||||
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);
|
||||
/* action function declaration with ss_ptr as parameter */
|
||||
printf("static void A_%s_%s(sprog, ss_ptr, var_ptr)\n", ssp->value, sp->value);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
printf("static 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(ss_ptr->trans_num)\n\t{\n");
|
||||
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)
|
||||
{
|
||||
@@ -97,7 +157,11 @@ Expr *ssp; /* Parent state set */
|
||||
/* For each action statement insert action code */
|
||||
for (ap = tp->right; ap != NULL; ap = ap->next)
|
||||
{
|
||||
print_line_num(ap->line_num, ap->src_file);
|
||||
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);
|
||||
}
|
||||
@@ -122,18 +186,21 @@ Expr *ssp;
|
||||
|
||||
printf("\n/* Event function for state \"%s\" in state set \"%s\" */\n",
|
||||
sp->value, ssp->value);
|
||||
printf("static int E_%s_%s(sprog, ss_ptr, var_ptr)\n", ssp->value, sp->value);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
printf("static 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 (");
|
||||
eval_expr(EVENT_STMT, tp->left, sp, 0);
|
||||
/* an event triggered, set next state */
|
||||
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);
|
||||
@@ -146,8 +213,8 @@ Expr *ssp;
|
||||
printf("\t\t/* state %s does not exist */\n",
|
||||
tp->value);
|
||||
}
|
||||
printf("\t\tss_ptr->next_state = %d;\n", index);
|
||||
printf("\t\tss_ptr->trans_num = %d;\n", trans_num);
|
||||
printf("\t\t*pNextState = %d;\n", index);
|
||||
printf("\t\t*pTransNum = %d;\n", trans_num);
|
||||
printf("\t\treturn TRUE;\n\t}\n");
|
||||
trans_num++;
|
||||
}
|
||||
@@ -173,32 +240,6 @@ char *state_name;
|
||||
}
|
||||
return -1; /* State name non-existant */
|
||||
}
|
||||
|
||||
/* Generate delay processing function for a state */
|
||||
gen_delay_func(sp, ssp)
|
||||
Expr *sp;
|
||||
Expr *ssp;
|
||||
{
|
||||
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(sprog, ss_ptr, var_ptr)\n", ssp->value, sp->value);
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("SSCB\t*ss_ptr;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
|
||||
/* For each transition ... */
|
||||
for (tp = sp->left; tp != NULL; tp = tp->next)
|
||||
{
|
||||
print_line_num(tp->line_num, tp->src_file);
|
||||
traverseExprTree(tp, E_FUNC, "delay", eval_delay, sp);
|
||||
}
|
||||
printf("}\n");
|
||||
|
||||
return;
|
||||
}
|
||||
/* Evaluate an expression.
|
||||
*/
|
||||
eval_expr(stmt_type, ep, sp, level)
|
||||
@@ -210,6 +251,8 @@ int level; /* indentation level */
|
||||
Expr *epf;
|
||||
int nparams;
|
||||
extern int reent_opt;
|
||||
extern int line_num;
|
||||
|
||||
if (ep == 0)
|
||||
return;
|
||||
|
||||
@@ -218,17 +261,20 @@ int level; /* indentation level */
|
||||
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:
|
||||
@@ -239,6 +285,7 @@ int level; /* indentation level */
|
||||
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);
|
||||
@@ -254,6 +301,7 @@ int level; /* indentation level */
|
||||
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);
|
||||
@@ -263,6 +311,7 @@ int level; /* indentation level */
|
||||
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)
|
||||
@@ -271,12 +320,15 @@ int level; /* indentation level */
|
||||
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("(var_ptr->%s)", ep->value);
|
||||
printf("(pVar->%s)", ep->value);
|
||||
else
|
||||
printf("%s", ep->value);
|
||||
}
|
||||
@@ -292,13 +344,16 @@ int level; /* indentation level */
|
||||
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);
|
||||
for (epf = ep->left, nparams = 0; epf != 0;
|
||||
epf = epf->next, nparams++)
|
||||
for (epf = ep->left, nparams = 0; epf != 0; epf = epf->next, nparams++)
|
||||
{
|
||||
if (nparams > 0)
|
||||
printf(" ,");
|
||||
@@ -337,6 +392,7 @@ int level; /* indentation level */
|
||||
break;
|
||||
case E_TEXT:
|
||||
printf("%s\n", ep->left);
|
||||
line_num += 1;
|
||||
break;
|
||||
default:
|
||||
if (stmt_type == EVENT_STMT)
|
||||
@@ -355,16 +411,22 @@ int level;
|
||||
}
|
||||
/* 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_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_PVCONNECTED, F_PVCHANNELCOUNT, F_PVCONNECTCOUNT, F_NONE };
|
||||
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",
|
||||
"pvGet", "pvPut", "pvTimeStamp", "pvAssign",
|
||||
"pvMonitor", "pvStopMonitor", "pvCount", "pvIndex",
|
||||
"pvStatus", "pvSeverity", "pvFlush", "pvError", "pvGetComplete",
|
||||
"pvConnected", "pvChannelCount", "pvConnectCount", NULL };
|
||||
"pvAssigned", "pvConnected",
|
||||
"pvChannelCount", "pvConnectCount", "pvAssignCount",
|
||||
"pvDisconnect", "seqLog", "macValueGet", "optGet",
|
||||
NULL };
|
||||
|
||||
enum fcode func_name_to_code(fname)
|
||||
char *fname;
|
||||
@@ -382,9 +444,11 @@ char *fname;
|
||||
|
||||
/* Process special function (returns TRUE if this is a special function)
|
||||
Checks for one of the following special functions:
|
||||
- event flag functions
|
||||
- process variable 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 */
|
||||
@@ -392,113 +456,206 @@ Expr *ep; /* ptr to function in the expression */
|
||||
Expr *sp; /* current State struct */
|
||||
{
|
||||
char *fname; /* function name */
|
||||
Expr *ep1; /* 1-st parameter */
|
||||
Expr *ep1, *ep2, *ep3; /* parameters */
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
enum fcode func_code;
|
||||
int ndelay;
|
||||
int delay_id;
|
||||
|
||||
fname = ep->value;
|
||||
func_code = func_name_to_code(fname);
|
||||
if (func_code == F_NONE)
|
||||
return FALSE; /* not a special function */
|
||||
|
||||
ep1 = ep->left; /* ptr to 1-st parameters */
|
||||
if ( (ep1 != 0) && (ep1->type == E_VAR) )
|
||||
{
|
||||
vp = (Var *)findVar(ep1->value);
|
||||
cp = vp->chan;
|
||||
}
|
||||
else
|
||||
{
|
||||
vp = 0;
|
||||
cp = 0;
|
||||
}
|
||||
|
||||
#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:
|
||||
if (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("%s(%s)", fname, vp->name);
|
||||
}
|
||||
/* Event flag funtions */
|
||||
gen_ef_func(stmt_type, ep, sp, fname);
|
||||
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:
|
||||
/* DB functions requiring a channel structure */
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "Line %d: ", ep->line_num);
|
||||
fprintf(stderr,
|
||||
"Parameter to \"%s\" must be DB variable.\n", fname);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s(%d)", fname, cp->index);
|
||||
}
|
||||
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:
|
||||
/* DB functions not requiring a channel structure */
|
||||
printf("%s()", fname);
|
||||
case F_PVASSIGNCOUNT:
|
||||
/* DB functions NOT requiring a channel structure */
|
||||
printf("seq_%s(ssId)", fname);
|
||||
return TRUE;
|
||||
|
||||
case F_DELAY:
|
||||
/* Test for delay: "test_delay(delay_id)" */
|
||||
printf("test_delay(%d)", (int)ep->right);
|
||||
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 */
|
||||
for (ep1 = ep->left; ep1 != 0; ep1 = ep1->next)
|
||||
{
|
||||
printf(", ");
|
||||
eval_expr(stmt_type, ep1, sp, 0);
|
||||
}
|
||||
printf(") ");
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE; /* not a special function */
|
||||
/* Not a special function */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Evaluate delay expression. */
|
||||
eval_delay(ep, sp)
|
||||
Expr *ep; /* ptr to expression */
|
||||
Expr *sp; /* ptr to current State struct */
|
||||
/* 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 *epf;
|
||||
int delay_id;
|
||||
extern char *stype[];
|
||||
Expr *ep1, *ep2, *ep3;
|
||||
Var *vp;
|
||||
Chan *cp;
|
||||
|
||||
ep1 = ep->left; /* ptr to 1-st parameters */
|
||||
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)
|
||||
{
|
||||
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, "eval_delay: type=%s\n", stype[ep->type]);
|
||||
#endif
|
||||
fprintf(stderr, "gen_pv_func: var=%s\n", ep1->value);
|
||||
#endif DEBUG
|
||||
cp = vp->chan;
|
||||
index = cp->index;
|
||||
}
|
||||
|
||||
delay_id = (int)ep->right;
|
||||
printf("\tstart_delay(%d, ", delay_id);
|
||||
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;
|
||||
}
|
||||
|
||||
/* Output each parameter */
|
||||
eval_expr(EVENT_STMT, ep->left, sp, 0);
|
||||
printf("seq_%s(ssId, %d", fname, index);
|
||||
|
||||
printf(");\n");
|
||||
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()
|
||||
@@ -507,9 +664,9 @@ gen_exit_handler()
|
||||
Expr *ep;
|
||||
|
||||
printf("/* Exit handler */\n");
|
||||
printf("static void exit_handler(sprog, var_ptr)\n");
|
||||
printf("SPROG\t*sprog;\n");
|
||||
printf("struct UserVar\t*var_ptr;\n{\n");
|
||||
printf("static 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);
|
||||
|
||||
@@ -3,18 +3,23 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
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.
|
||||
***************************************************************************/
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include <dbDefs.h>
|
||||
#include <seqU.h>
|
||||
#include <seqCom.h>
|
||||
|
||||
/*+************************************************************************
|
||||
* NAME: gen_tables
|
||||
@@ -30,8 +35,6 @@
|
||||
* NOTES: All inputs are external globals.
|
||||
*-*************************************************************************/
|
||||
|
||||
int nstates; /* total # states in all state sets */
|
||||
|
||||
gen_tables()
|
||||
{
|
||||
extern Expr *ss_list; /* state sets (from parse) */
|
||||
@@ -45,11 +48,14 @@ gen_tables()
|
||||
/* Generate State Blocks */
|
||||
gen_state_blocks();
|
||||
|
||||
/* Generate State Set control blocks as an array */
|
||||
gen_sscb_array();
|
||||
/* Generate State Set Blocks */
|
||||
gen_ss_array();
|
||||
|
||||
/* generate program parameter string */
|
||||
gen_prog_params();
|
||||
|
||||
/* Generate state program table */
|
||||
gen_state_prog_table();
|
||||
gen_prog_table();
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -58,254 +64,250 @@ gen_db_blocks()
|
||||
{
|
||||
extern Chan *chan_list;
|
||||
Chan *cp;
|
||||
int nchan;
|
||||
int nchan, elem_num;
|
||||
|
||||
printf("\n/* Database Blocks */\n");
|
||||
printf("static CHAN db_channels[NUM_CHANNELS] = {\n");
|
||||
printf("static struct seqChan seqChan[NUM_CHANNELS] = {\n");
|
||||
nchan = 0;
|
||||
|
||||
for (cp = chan_list; cp != NULL; cp = cp->next)
|
||||
{
|
||||
/* Only process db variables */
|
||||
if (cp->db_name != NULL)
|
||||
{
|
||||
if (nchan > 0)
|
||||
printf(",\n");
|
||||
fill_db_block(cp, nchan);
|
||||
#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};\n");
|
||||
printf("};\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill in a db block with data (all elements for "CHAN" struct) */
|
||||
fill_db_block(cp, index)
|
||||
/* Fill in a db block with data (all elements for "seqChan" struct) */
|
||||
fill_db_block(cp, elem_num)
|
||||
Chan *cp;
|
||||
int index;
|
||||
int elem_num;
|
||||
{
|
||||
Var *vp;
|
||||
char *get_type_string, *put_type_string, *postfix;
|
||||
char *type_string, *suffix, elem_str[20], *db_name;
|
||||
extern char *prog_name;
|
||||
extern int reent_opt;
|
||||
int size, ev_flag, count;
|
||||
extern int reent_opt;
|
||||
extern int num_events;
|
||||
int size, count, ef_num, mon_flag;
|
||||
char *db_type_str();
|
||||
|
||||
vp = cp->var;
|
||||
/* Convert variable type to a DB request type */
|
||||
switch (vp->type)
|
||||
|
||||
/* 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)
|
||||
{
|
||||
case V_SHORT:
|
||||
get_type_string = "DBR_STS_INT";
|
||||
put_type_string = "DBR_INT";
|
||||
size = sizeof(short);
|
||||
break;
|
||||
case V_INT:
|
||||
case V_LONG:
|
||||
/* Assume "long" & "int" are same size */
|
||||
get_type_string = "DBR_STS_LONG";
|
||||
put_type_string = "DBR_LONG";
|
||||
size = sizeof(int);
|
||||
break;
|
||||
case V_CHAR:
|
||||
get_type_string = "DBR_STS_CHAR";
|
||||
put_type_string = "DBR_CHAR";
|
||||
size = sizeof(char);
|
||||
break;
|
||||
case V_FLOAT:
|
||||
get_type_string = "DBR_STS_FLOAT";
|
||||
put_type_string = "DBR_FLOAT";
|
||||
size = sizeof(float);
|
||||
break;
|
||||
case V_DOUBLE:
|
||||
get_type_string = "DBR_STS_DOUBLE";
|
||||
put_type_string = "DBR_DOUBLE";
|
||||
size = sizeof(double);
|
||||
break;
|
||||
case V_STRING:
|
||||
get_type_string = "DBR_STS_STRING";
|
||||
put_type_string = "DBR_STRING";
|
||||
size = MAX_STRING_SIZE;
|
||||
break;
|
||||
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];
|
||||
}
|
||||
|
||||
/* fill in the CHAN structure */
|
||||
printf("\t%d, ", index); /* index for this channel */
|
||||
if (db_name == NULL)
|
||||
db_name = ""; /* not assigned */
|
||||
|
||||
printf("\"%s\", ", cp->db_name);/* unexpanded db channel name */
|
||||
/* Now, fill in the dbCom structure */
|
||||
|
||||
printf("(char *)0, "); /* ch'l name after macro expansion */
|
||||
printf(" \"%s\", ", db_name);/* unexpanded db channel name */
|
||||
|
||||
/* Ptr or offset to user variable */
|
||||
printf("(char *)");
|
||||
if (vp->type == V_STRING || cp->count > 0)
|
||||
postfix = "[0]";
|
||||
else
|
||||
postfix = "";
|
||||
printf("(void *)");
|
||||
if (reent_opt)
|
||||
printf("OFFSET(struct UserVar, %s%s), ", vp->name, postfix);
|
||||
printf("OFFSET(struct UserVar, %s%s%s), ", vp->name, elem_str, suffix);
|
||||
else
|
||||
printf("&%s%s, ", vp->name, postfix); /* variable ptr */
|
||||
printf("&%s%s%s, ", vp->name, elem_str, suffix); /* variable ptr */
|
||||
|
||||
printf("(chid)0, "); /* reserve place for chid */
|
||||
/* variable name with optional elem num */
|
||||
printf("\"%s%s\", ", vp->name, elem_str);
|
||||
|
||||
printf("0, 0, 0, 0, "); /* connected, get_complete, status, severity */
|
||||
/* variable type */
|
||||
printf("\n \"%s\", ", db_type_str(vp->type) );
|
||||
|
||||
printf("%d,\n", size); /* element size (bytes) */
|
||||
/* count for db requests */
|
||||
printf("%d, ", cp->count);
|
||||
|
||||
printf("\t%s, ", get_type_string);/* DB request conversion type (get/mon) */
|
||||
/* event number */
|
||||
printf("%d, ", cp->index + elem_num + num_events + 1);
|
||||
|
||||
printf("%s, ", put_type_string);/* DB request conversion type (put) */
|
||||
/* event flag number (or 0) */
|
||||
printf("%d, ", ef_num);
|
||||
|
||||
count = cp->count;
|
||||
if (count == 0)
|
||||
count = 1;
|
||||
printf("%d, ", count); /* count for db requests */
|
||||
/* monitor flag */
|
||||
printf("%d", mon_flag);
|
||||
|
||||
printf("%d, ", cp->mon_flag); /* monitor flag */
|
||||
|
||||
printf("0, "); /* monitored */
|
||||
|
||||
printf("%g, ", cp->delta); /* monitor delta */
|
||||
|
||||
printf("%g, ", cp->timeout); /* monitor timeout */
|
||||
|
||||
printf("0, "); /* event id supplied by CA */
|
||||
|
||||
printf("0, "); /* semaphore id for async. pvGet() */
|
||||
|
||||
printf("&%s", prog_name); /* ptr to state program structure */
|
||||
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_FLOAT: return "float";
|
||||
case V_DOUBLE: return "double";
|
||||
case V_STRING: return "string";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate structure and data for state blocks (STATE) */
|
||||
/* Generate structure and data for state blocks */
|
||||
gen_state_blocks()
|
||||
{
|
||||
extern Expr *ss_list;
|
||||
Expr *ssp;
|
||||
Expr *sp;
|
||||
int ns;
|
||||
extern int nstates;
|
||||
int nstates, n;
|
||||
extern int num_events, num_channels;
|
||||
int numEventWords;
|
||||
bitMask *pEventMask;
|
||||
|
||||
printf("\n/* State Blocks:\n");
|
||||
printf(" action_func, event_func, delay_func, event_flag_mask");
|
||||
printf(", *delay, *name */\n");
|
||||
|
||||
nstates = 0;
|
||||
/* Allocate an array for event mask bits */
|
||||
numEventWords = (num_events + num_channels + NBITS - 1)/NBITS;
|
||||
pEventMask = (bitMask *)calloc(numEventWords, sizeof (bitMask));
|
||||
|
||||
/* for all state sets ... */
|
||||
for (ssp = ss_list; ssp != NULL; ssp = ssp->next)
|
||||
{
|
||||
printf("\nstatic STATE state_%s[] = {\n", ssp->value);
|
||||
ns = 0;
|
||||
/* 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)
|
||||
{
|
||||
if (ns > 0)
|
||||
printf(",\n\n");
|
||||
ns++;
|
||||
nstates++;
|
||||
fill_state_block(sp, ssp->value);
|
||||
}
|
||||
printf("\n};\n");
|
||||
}
|
||||
|
||||
free(pEventMask);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fill in data for a the state block */
|
||||
/* Fill in data for a state block (see seqState in seqCom.h) */
|
||||
fill_state_block(sp, ss_name)
|
||||
Expr *sp;
|
||||
char *ss_name;
|
||||
{
|
||||
bitMask events[NWRDS];
|
||||
int n;
|
||||
|
||||
printf("\t/* State \"%s\"*/\n", sp->value);
|
||||
|
||||
printf("\tA_%s_%s,\t/* action_function */\n", ss_name, sp->value);
|
||||
printf("\t/* state name */ \"%s\",\n", sp->value);
|
||||
|
||||
printf("\tE_%s_%s,\t/* event_function */\n", ss_name, sp->value);
|
||||
printf("\t/* action function */ A_%s_%s,\n", ss_name, sp->value);
|
||||
|
||||
printf("\tD_%s_%s,\t/* delay_function */\n", ss_name, sp->value);
|
||||
printf("\t/* event function */ E_%s_%s,\n", ss_name, sp->value);
|
||||
|
||||
eval_state_event_mask(sp, events);
|
||||
printf("\t/* Event mask for this state: */\n");
|
||||
for (n = 0; n < NWRDS; n++)
|
||||
printf("\t0x%08x,\n", events[n]);
|
||||
printf("\t/* delay function */ D_%s_%s,\n", ss_name, sp->value);
|
||||
|
||||
printf("\t\"%s\"\t/* *name */", sp->value);
|
||||
printf("\t/* event mask array */ EM_%s_%s,\n\n", ss_name, sp->value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate the structure with data for a state program table (SPROG) */
|
||||
gen_state_prog_table()
|
||||
/* Generate the program parameter list */
|
||||
gen_prog_params()
|
||||
{
|
||||
extern char *prog_name, *prog_param;
|
||||
extern int async_opt, debug_opt, reent_opt, conn_opt, newef_opt;
|
||||
extern int nstates;
|
||||
extern Expr exit_code_list;
|
||||
int i;
|
||||
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("SPROG %s = {\n", prog_name);
|
||||
printf("struct seqProgram %s = {\n", prog_name);
|
||||
|
||||
printf("\t%d,\t/* magic number */\n", MAGIC);
|
||||
printf("\t/* magic number */ %d,\n", MAGIC); /* magic number */
|
||||
|
||||
printf("\t0,\t/* task id */\n");
|
||||
printf("\t/* *name */ \"%s\",\n", prog_name);/* program name */
|
||||
|
||||
printf("\t0,\t/* dyn_ptr */\n");
|
||||
printf("\t/* *pChannels */ seqChan,\n"); /* table of db channels */
|
||||
|
||||
printf("\t0,\t/* task_is_deleted */\n");
|
||||
printf("\t/* numChans */ NUM_CHANNELS,\n"); /* number of db channels */
|
||||
|
||||
printf("\t1,\t/* relative task priority */\n");
|
||||
printf("\t/* *pSS */ seqSS,\n"); /* array of SS blocks */
|
||||
|
||||
printf("\t0,\t/* caSemId */\n");
|
||||
|
||||
printf("\tdb_channels,\t/* *channels */\n");
|
||||
|
||||
printf("\tNUM_CHANNELS,\t/* nchan */\n");
|
||||
|
||||
printf("\t0,\t/* conn_count */\n");
|
||||
|
||||
printf("\tsscb,\t/* *sscb */\n");
|
||||
|
||||
printf("\tNUM_SS,\t/* nss */\n");
|
||||
|
||||
printf("\tNULL,\t/* ptr to states */\n");
|
||||
|
||||
printf("\t%d,\t/* number of states */\n", nstates);
|
||||
|
||||
printf("\tNULL,\t/* ptr to user area (not used) */\n");
|
||||
printf("\t/* numSS */ NUM_SS,\n"); /* number of state sets */
|
||||
|
||||
if (reent_opt)
|
||||
printf("\tsizeof(struct UserVar),\t/* user area size */\n");
|
||||
printf("\t/* user variable size */ sizeof(struct UserVar),\n");
|
||||
else
|
||||
printf("\t0,\t/* user area size (not used) */\n");
|
||||
printf("\t/* user variable size */ 0,\n");
|
||||
|
||||
printf("\tNULL,\t/* mac_ptr */\n");
|
||||
printf("\t/* *pParams */ prog_param,\n"); /* program parameters */
|
||||
|
||||
printf("\tNULL,\t/* scr_ptr */\n");
|
||||
printf("\t/* numEvents */ NUM_EVENTS,\n"); /* number event flags */
|
||||
|
||||
printf("\t0,\t/* scr_nleft */\n");
|
||||
printf("\t/* encoded options */ ");
|
||||
encode_options();
|
||||
|
||||
printf("\t\"%s\",\t/* *name */\n", prog_name);
|
||||
|
||||
printf("\tprog_param,\t/* *params */\n");
|
||||
|
||||
printf("\t");
|
||||
for (i = 0; i < NWRDS; i++)
|
||||
printf("0, ");
|
||||
printf("\t/* Event flags (bit encoded) */\n");
|
||||
|
||||
printf("\t0x%x,\t/* encoded async, debug, conn, newef & reent options */\n",
|
||||
encode_options() );
|
||||
|
||||
printf("\texit_handler,\t/* exit handler */\n");
|
||||
|
||||
printf("\t0, 0\t/* logSemId & logFd */\n");
|
||||
printf("\t/* exit handler */ exit_handler,\n");
|
||||
|
||||
printf("};\n");
|
||||
|
||||
@@ -314,71 +316,55 @@ gen_state_prog_table()
|
||||
|
||||
encode_options()
|
||||
{
|
||||
int options;
|
||||
extern int async_opt, debug_opt, reent_opt, conn_opt, newef_opt;
|
||||
extern int async_opt, debug_opt, reent_opt,
|
||||
newef_opt, conn_opt, vx_opt;
|
||||
|
||||
options = 0;
|
||||
printf("(0");
|
||||
if (async_opt)
|
||||
options |= OPT_ASYNC;
|
||||
printf(" | OPT_ASYNC");
|
||||
if (conn_opt)
|
||||
options |= OPT_CONN;
|
||||
printf(" | OPT_CONN");
|
||||
if (debug_opt)
|
||||
options |= OPT_DEBUG;
|
||||
if (reent_opt)
|
||||
options |= OPT_REENT;
|
||||
printf(" | OPT_DEBUG");
|
||||
if (newef_opt)
|
||||
options |= OPT_NEWEF;
|
||||
return options;
|
||||
printf(" | OPT_NEWEF");
|
||||
if (reent_opt)
|
||||
printf(" | OPT_REENT");
|
||||
if (vx_opt)
|
||||
printf(" | OPT_VXWORKS");
|
||||
printf("),\n");
|
||||
|
||||
return;
|
||||
}
|
||||
/* Generate an array of state set control blocks (SSCB),
|
||||
one entry for each state set */
|
||||
gen_sscb_array()
|
||||
/* 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;
|
||||
bitMask events[NWRDS];
|
||||
|
||||
printf("\n/* State Set Control Blocks */\n");
|
||||
printf("static SSCB sscb[NUM_SS] = {\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");
|
||||
printf("\n\n");
|
||||
nss++;
|
||||
|
||||
printf("\t/* State set \"%s\"*/\n", ssp->value);
|
||||
|
||||
printf("\t0, 1,\t/* task_id, task_prioity */\n");
|
||||
printf("\t/* ss name */ \"%s\",\n", ssp->value);
|
||||
|
||||
printf("\t0, 0,\t/* caSemId, getSemId */\n");
|
||||
printf("\t/* ptr to state block */ state_%s%,\n", ssp->value);
|
||||
|
||||
nstates = exprCount(ssp->left);
|
||||
printf("\t%d, state_%s,\t/* num_states, *states */\n", nstates,
|
||||
ssp->value);
|
||||
printf("\t/* number of states */ %d,\n", nstates, ssp->value);
|
||||
|
||||
printf("\t0, 0, 0,");
|
||||
printf("\t/* current_state, next_state, prev_state */\n");
|
||||
printf("\t/* error state */ %d,\n", find_error_state(ssp));
|
||||
|
||||
printf("\t%d,\t/* error_state */\n", find_error_state(ssp));
|
||||
|
||||
printf("\t0, FALSE,\t/* trans_number, action_complete */\n");
|
||||
|
||||
printf("\t0,\t/* pMask - ptr to current event mask */\n");
|
||||
|
||||
printf("\t0,\t/* number of delays in use */\n");
|
||||
|
||||
printf("\t/* array of delay values: */\n\t");
|
||||
for (n = 0; n < MAX_NDELAY; n++)
|
||||
printf("0,");
|
||||
printf("\n");
|
||||
|
||||
printf("\t0,\t/* time (ticks) when state was entered */\n");
|
||||
|
||||
printf("\t\"%s\"\t\t/* ss name */", ssp->value);
|
||||
}
|
||||
printf("\n};\n");
|
||||
printf("};\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -397,42 +383,146 @@ Expr *ssp;
|
||||
}
|
||||
|
||||
/* Evaluate composite event mask for a single state */
|
||||
eval_state_event_mask(sp, events)
|
||||
eval_state_event_mask(sp, pEventWords, numEventWords)
|
||||
Expr *sp;
|
||||
bitMask events[NWRDS];
|
||||
bitMask *pEventWords;
|
||||
int numEventWords;
|
||||
{
|
||||
int n;
|
||||
int eval_tr_event_mask();
|
||||
int eval_event_mask(), eval_event_mask_subscr();
|
||||
Expr *tp;
|
||||
|
||||
/* Clear all bits in mask */
|
||||
for (n = 0; n < NWRDS; n++)
|
||||
events[n] = 0;
|
||||
/* 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;
|
||||
|
||||
/* Set appropriate bits based on transition expressions */
|
||||
for (tp = sp->left; tp != 0; tp = tp->next)
|
||||
traverseExprTree(tp->left, E_VAR, 0,
|
||||
eval_tr_event_mask, events);
|
||||
{
|
||||
/* 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. */
|
||||
eval_tr_event_mask(ep, events)
|
||||
/* 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 events[NWRDS];
|
||||
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_tr_event_mask: %s, ef_num=%d\n",
|
||||
vp->name, vp->ef_num);
|
||||
fprintf(stderr, " eval_event_mask: %s, ef_num=%d\n",
|
||||
vp->name, vp->ef_num);
|
||||
#endif
|
||||
if (vp->ef_num != 0)
|
||||
bitSet(events, vp->ef_num);
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
for (n = 0; n < vp->length1; n++)
|
||||
{
|
||||
bitSet(pEventWords, cp->index + n + num_events + 1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Count the number of linked expressions */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
< 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.
|
||||
@@ -15,6 +15,10 @@
|
||||
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 ====================*/
|
||||
@@ -22,12 +26,11 @@
|
||||
#include <stdio.h>
|
||||
#include "parse.h" /* defines linked list structures */
|
||||
#include <math.h>
|
||||
#include "db_access.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif /* TRUE */
|
||||
#endif TRUE
|
||||
|
||||
int debug_print_opt = 0; /* Debug level (set by source file) */
|
||||
|
||||
@@ -65,8 +68,6 @@ Expr *global_c_list; /* global C code following state program */
|
||||
program_name(pname, pparam)
|
||||
char *pname, *pparam;
|
||||
{
|
||||
extern char *prog_name, *prog_param;
|
||||
|
||||
prog_name = pname;
|
||||
prog_param = pparam;
|
||||
#ifdef DEBUG
|
||||
@@ -76,29 +77,40 @@ char *pname, *pparam;
|
||||
}
|
||||
|
||||
/* Parsing a declaration statement */
|
||||
decl_stmt(type, name, s_length, value)
|
||||
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_length; /* array lth (NULL=single element) */
|
||||
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 length;
|
||||
int length1, length2;
|
||||
extern int line_num;
|
||||
|
||||
if (s_length == 0)
|
||||
length = 0;
|
||||
else if (type == V_STRING)
|
||||
length = 0;
|
||||
else
|
||||
{
|
||||
length = atoi(s_length);
|
||||
if (length < 0)
|
||||
length = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "variable decl: type=%d, name=%s, length=%d\n",
|
||||
type, name, length);
|
||||
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);
|
||||
@@ -112,9 +124,12 @@ char *value; /* initial value or NULL */
|
||||
vp = allocVar();
|
||||
addVar(vp); /* add to var list */
|
||||
vp->name = name;
|
||||
vp->class = class;
|
||||
vp->type = type;
|
||||
vp->length = length;
|
||||
vp->length1 = length1;
|
||||
vp->length2 = length2;
|
||||
vp->value = value; /* initial value or NULL */
|
||||
vp->chan = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -123,8 +138,8 @@ 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, newef_opt;
|
||||
extern int async_opt, conn_opt, debug_opt, line_opt,
|
||||
reent_opt, warn_opt, vx_opt, newef_opt;
|
||||
|
||||
switch(*option)
|
||||
{
|
||||
@@ -137,6 +152,10 @@ int value; /* TRUE means +, FALSE means - */
|
||||
case 'd':
|
||||
debug_opt = value;
|
||||
break;
|
||||
case 'e':
|
||||
newef_opt = value;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
line_opt = value;
|
||||
break;
|
||||
@@ -145,28 +164,30 @@ int value; /* TRUE means +, FALSE means - */
|
||||
break;
|
||||
case 'w':
|
||||
warn_opt = value;
|
||||
|
||||
case 'e':
|
||||
newef_opt = value;
|
||||
|
||||
break;
|
||||
case 'v':
|
||||
vx_opt = value;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* "Assign" statement: assign a variable to a DB channel.
|
||||
elem_num is ignored in this version) */
|
||||
assign_stmt(name, db_name)
|
||||
/* "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_stmt: name=%s, db_name=%s\n", name, db_name);
|
||||
#endif /* DEBUG */
|
||||
fprintf(stderr, "assign %s to \"%s\";\n", name, db_name);
|
||||
#endif DEBUG
|
||||
/* Find the variable */
|
||||
vp = (Var *)findVar(name);
|
||||
if (vp == 0)
|
||||
@@ -176,29 +197,240 @@ char *db_name; /* ptr to db name */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Build structure for this channel */
|
||||
cp = allocChan();
|
||||
addChan(cp); /* add to Chan list */
|
||||
cp->var = vp; /* make connection to variable */
|
||||
vp->chan = cp; /* reverse ptr */
|
||||
cp->db_name = db_name; /* DB name */
|
||||
cp->count = vp->length; /* default count is variable length */
|
||||
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;
|
||||
|
||||
cp->mon_flag = FALSE; /* assume no monitor */
|
||||
cp->ef_var = NULL; /* assume no sync event flag */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Parsing a "monitor" statement */
|
||||
monitor_stmt(name, delta)
|
||||
char *name; /* variable name (should be assigned) */
|
||||
char *delta; /* monitor delta */
|
||||
/* "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;
|
||||
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 = (Chan *)findChan(name);
|
||||
cp = vp->chan;
|
||||
if (cp == 0)
|
||||
{
|
||||
fprintf(stderr, "monitor: variable %s not assigned, line %d\n",
|
||||
@@ -206,22 +438,67 @@ char *delta; /* monitor delta */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enter monitor parameters */
|
||||
cp->mon_flag = TRUE;
|
||||
cp->delta = atof(delta);
|
||||
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, ef_name)
|
||||
char *name;
|
||||
char *ef_name;
|
||||
sync_stmt(name, subscript, ef_name)
|
||||
char *name;
|
||||
char *subscript;
|
||||
char *ef_name;
|
||||
{
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
extern int line_num;
|
||||
int subNum;
|
||||
|
||||
cp = (Chan *)findChan(name);
|
||||
#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",
|
||||
@@ -238,36 +515,56 @@ char *ef_name;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Insert pointers between Var & Chan structures */
|
||||
cp->ef_var = vp;
|
||||
vp->chan = cp;
|
||||
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_str)
|
||||
char *c_str; /* ptr to C code string */
|
||||
defn_c_stmt(c_list)
|
||||
Expr *c_list; /* ptr to C code */
|
||||
{
|
||||
Expr *ep;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "defn_c_stmt\n");
|
||||
#endif
|
||||
ep = expression(E_TEXT, "", c_str, 0);
|
||||
if (defn_c_list == 0)
|
||||
defn_c_list = ep;
|
||||
defn_c_list = c_list;
|
||||
else
|
||||
link_expr(defn_c_list, ep);
|
||||
link_expr(defn_c_list, c_list);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Global C code (follows state program) */
|
||||
global_c_stmt(c_str)
|
||||
char *c_str; /* ptr to C code */
|
||||
global_c_stmt(c_list)
|
||||
Expr *c_list; /* ptr to C code */
|
||||
{
|
||||
global_c_list = expression(E_TEXT, "", c_str, 0);
|
||||
global_c_list = c_list;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -292,22 +589,13 @@ char *name;
|
||||
{
|
||||
Var *vp;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "findVar, name=%s: ", name);
|
||||
#endif
|
||||
for (vp = var_list; vp != NULL; vp = vp->next)
|
||||
{
|
||||
if (strcmp(vp->name, name) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "found\n");
|
||||
#endif
|
||||
return vp;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "not found\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -322,35 +610,6 @@ Chan *cp;
|
||||
chan_tail = cp;
|
||||
cp->next = NULL;
|
||||
}
|
||||
|
||||
/* Find a channel with a given associated variable name */
|
||||
Chan *findChan(name)
|
||||
char *name; /* variable name */
|
||||
{
|
||||
Chan *cp;
|
||||
Var *vp;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "findChan, var name=%s: ", name);
|
||||
#endif
|
||||
for (cp = chan_list; cp != NULL; cp = cp->next)
|
||||
{
|
||||
vp = cp->var;
|
||||
if (vp == 0)
|
||||
continue;
|
||||
if (strcmp(vp->name, name) == 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "found chan name=%s\n", cp->db_name);
|
||||
#endif
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "not found\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set debug print opt */
|
||||
set_debug_print(opt)
|
||||
@@ -366,7 +625,7 @@ Expr *prog_list;
|
||||
ss_list = prog_list;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "----Phase2---\n");
|
||||
#endif /* DEBUG */
|
||||
#endif DEBUG
|
||||
phase2(ss_list);
|
||||
|
||||
exit(0);
|
||||
@@ -442,7 +701,7 @@ Expr *ep2; /* beginning 2-nd (append it to 1-st) */
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, ")\n");
|
||||
#endif /* DEBUG */
|
||||
#endif DEBUG
|
||||
return ep1;
|
||||
}
|
||||
|
||||
@@ -452,7 +711,7 @@ char *line;
|
||||
char *fname;
|
||||
{
|
||||
extern int line_num;
|
||||
extern char *src_file;
|
||||
extern char *src_file;
|
||||
|
||||
line_num = atoi(line);
|
||||
src_file = fname;
|
||||
@@ -462,4 +721,6 @@ char *fname;
|
||||
char *stype[] = {
|
||||
"E_EMPTY", "E_CONST", "E_VAR", "E_FUNC", "E_STRING", "E_UNOP", "E_BINOP",
|
||||
"E_ASGNOP", "E_PAREN", "E_SUBSCR", "E_TEXT", "E_STMT", "E_CMPND",
|
||||
"E_IF", "E_ELSE", "E_WHILE", "E_SS", "E_STATE", "E_WHEN" };
|
||||
"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_?" };
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1989, The Regents of the University of California.
|
||||
Copyright, 1989-93, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
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
|
||||
@@ -34,41 +38,47 @@ struct var /* Variable or function definition */
|
||||
char *name; /* variable name */
|
||||
char *value; /* initial value or NULL */
|
||||
int type; /* var type */
|
||||
int length; /* array lth (0 if not an array) */
|
||||
int ef_num; /* event flag bit number */
|
||||
struct db_chan *chan; /* ptr to db channel struct or NULL */
|
||||
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 info */
|
||||
struct db_chan /* DB channel assignment info */
|
||||
{
|
||||
struct db_chan *next; /* link to next item in list */
|
||||
char *db_name; /* database name */
|
||||
int index; /* channel array index */
|
||||
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 */
|
||||
Var *ef_var; /* ptr to event flag variable for sync */
|
||||
int count; /* count for db access */
|
||||
int mon_flag; /* TRUE if channel is "monitored" */
|
||||
float delta; /* monitor dead-band */
|
||||
float timeout; /* monitor timeout */
|
||||
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 *)malloc(sizeof(Expr));
|
||||
#define allocVar() (Var *)malloc(sizeof(Var));
|
||||
#define allocChan() (Chan *)malloc(sizeof(Chan));
|
||||
#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 (but converted to long) */
|
||||
#define V_INT 3 /* int */
|
||||
#define V_LONG 4 /* long */
|
||||
#define V_FLOAT 5 /* float */
|
||||
#define V_DOUBLE 6 /* double */
|
||||
@@ -77,9 +87,16 @@ Chan *findChan();
|
||||
#define V_FUNC 9 /* function (not a variable) */
|
||||
#define V_UCHAR 11 /* unsigned char */
|
||||
#define V_USHORT 12 /* unsigned short */
|
||||
#define V_UINT 13 /* unsigned int (converted to unsigned long) */
|
||||
#define V_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 */
|
||||
|
||||
@@ -3,23 +3,29 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
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
|
||||
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.
|
||||
***************************************************************************/
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "parse.h"
|
||||
#include <dbDefs.h>
|
||||
#include <seqU.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 */
|
||||
|
||||
/*+************************************************************************
|
||||
@@ -31,7 +37,7 @@ int num_errors = 0; /* number of errors detected in phase 2 processing */
|
||||
*
|
||||
* RETURNS: n/a
|
||||
*
|
||||
* FUNCTION: Generate C code from tables.
|
||||
* FUNCTION: Generate C code from parsing lists.
|
||||
*
|
||||
* NOTES: All inputs are external globals.
|
||||
*-*************************************************************************/
|
||||
@@ -51,6 +57,12 @@ phase2()
|
||||
/* 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();
|
||||
|
||||
@@ -60,12 +72,6 @@ phase2()
|
||||
/* Generate definition C code */
|
||||
gen_defn_c_code();
|
||||
|
||||
/* Assign bits for event flags */
|
||||
assign_ef_bits();
|
||||
|
||||
/* Assign delay id's */
|
||||
assign_delay_ids();
|
||||
|
||||
/* Generate code for each state set */
|
||||
gen_ss_code();
|
||||
|
||||
@@ -87,11 +93,16 @@ gen_preamble()
|
||||
printf("/* Program \"%s\" */\n", prog_name);
|
||||
|
||||
/* Include files */
|
||||
printf("#include \"seq.h\"\n");
|
||||
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");
|
||||
@@ -101,12 +112,13 @@ gen_preamble()
|
||||
printf("\n");
|
||||
|
||||
/* Forward references of tables: */
|
||||
printf("\nextern SPROG %s;\n", prog_name);
|
||||
printf("extern CHAN db_channels[];\n");
|
||||
printf("\nextern struct seqProgram %s;\n", prog_name);
|
||||
printf("extern struct seqChan seqChan[];\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Generate defines for compiler options */
|
||||
gen_opt_defn(opt, defn_name)
|
||||
int opt;
|
||||
char *defn_name;
|
||||
@@ -118,8 +130,9 @@ char *defn_name;
|
||||
}
|
||||
|
||||
/* Reconcile all variables in an expression,
|
||||
and tie each to the appropriate VAR struct */
|
||||
int printTree = FALSE;
|
||||
* and tie each to the appropriate VAR structure.
|
||||
*/
|
||||
int printTree = FALSE; /* For debugging only */
|
||||
|
||||
reconcile_variables()
|
||||
{
|
||||
@@ -131,7 +144,7 @@ reconcile_variables()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "reconcile_variables: ss=%s\n", ssp->value);
|
||||
#endif /* DEBUG */
|
||||
#endif DEBUG
|
||||
traverseExprTree(ssp, E_VAR, 0, connect_variable, 0);
|
||||
}
|
||||
|
||||
@@ -151,6 +164,11 @@ Expr *ep;
|
||||
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 */
|
||||
@@ -162,39 +180,39 @@ Expr *ep;
|
||||
addVar(vp);
|
||||
vp->name = ep->value;
|
||||
vp->type = V_NONE; /* undeclared type */
|
||||
vp->length = 0;
|
||||
vp->length1 = 1;
|
||||
vp->length2 = 1;
|
||||
vp->value = 0;
|
||||
}
|
||||
ep->left = (Expr *)vp; /* make connection */
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "connect_variable: %s\n", ep->value);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reconcile state names */
|
||||
reconcile_states()
|
||||
{
|
||||
|
||||
extern Expr *ss_list;
|
||||
|
||||
extern int num_errors;
|
||||
extern Expr *ss_list;
|
||||
Expr *ssp, *sp, *sp1, tr;
|
||||
|
||||
for (ssp = ss_list; ssp != 0; ssp = ssp->next)
|
||||
{
|
||||
for (sp = ssp->left; sp != 0; sp = sp->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)
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
if (strcmp(sp->value, sp1->value) == 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"State \"%s\" is duplicated in state set \"%s\"\n",
|
||||
sp->value, ssp->value);
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr,
|
||||
"State \"%s\" is duplicated in state set \"%s\"\n",
|
||||
sp->value, ssp->value);
|
||||
num_errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,47 +249,60 @@ gen_var_decl()
|
||||
{
|
||||
switch (vp->type)
|
||||
{
|
||||
case V_CHAR:
|
||||
case V_CHAR:
|
||||
vstr = "char";
|
||||
break;
|
||||
case V_INT:
|
||||
case V_LONG:
|
||||
case V_INT:
|
||||
vstr = "int";
|
||||
break;
|
||||
case V_LONG:
|
||||
vstr = "long";
|
||||
break;
|
||||
case V_SHORT:
|
||||
case V_SHORT:
|
||||
vstr = "short";
|
||||
break;
|
||||
case V_FLOAT:
|
||||
case V_FLOAT:
|
||||
vstr = "float";
|
||||
break;
|
||||
case V_DOUBLE:
|
||||
case V_DOUBLE:
|
||||
vstr = "double";
|
||||
break;
|
||||
case V_STRING:
|
||||
case V_STRING:
|
||||
vstr = "char";
|
||||
break;
|
||||
case V_EVFLAG:
|
||||
case V_NONE:
|
||||
case V_EVFLAG:
|
||||
case V_NONE:
|
||||
vstr = NULL;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
vstr = "int";
|
||||
break;
|
||||
}
|
||||
if (vstr == NULL)
|
||||
continue;
|
||||
|
||||
if (vstr != NULL)
|
||||
{
|
||||
if (reent_opt)
|
||||
printf("\t");
|
||||
else
|
||||
printf("static ");
|
||||
printf("%s\t%s", vstr, vp->name);
|
||||
if (vp->length > 0)
|
||||
printf("[%d]", vp->length);
|
||||
else if (vp->type == V_STRING)
|
||||
printf("[MAX_STRING_SIZE]");
|
||||
printf(";\n");
|
||||
}
|
||||
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]");
|
||||
|
||||
printf(";\n");
|
||||
}
|
||||
if (reent_opt)
|
||||
printf("};\n");
|
||||
@@ -306,16 +337,17 @@ gen_global_c_code()
|
||||
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)
|
||||
{
|
||||
print_line_num(ep->line_num, ep->src_file);
|
||||
printf("%s\n", ep->left);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns number of db channels defined & inserts index into each channel struct */
|
||||
/* Sets cp->index for each variable, & returns number of db channels defined.
|
||||
*/
|
||||
db_chan_count()
|
||||
{
|
||||
extern Chan *chan_list;
|
||||
@@ -325,57 +357,68 @@ db_chan_count()
|
||||
nchan = 0;
|
||||
for (cp = chan_list; cp != NULL; cp = cp->next)
|
||||
{
|
||||
if (cp->db_name != NULL)
|
||||
{
|
||||
cp->index = nchan;
|
||||
nchan++;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "db_name=%s, index=%d\n",
|
||||
cp->db_name, cp->index);
|
||||
#endif
|
||||
}
|
||||
cp->index = nchan;
|
||||
if (cp->num_elem == 0)
|
||||
nchan += 1;
|
||||
else
|
||||
nchan += cp->num_elem; /* array with multiple channels */
|
||||
}
|
||||
|
||||
return nchan;
|
||||
}
|
||||
|
||||
|
||||
/* Assign bits to event flags and database variables */
|
||||
/* Assign event bits to event flags and associate db channels with
|
||||
* event flags.
|
||||
*/
|
||||
assign_ef_bits()
|
||||
{
|
||||
extern Var *var_list;
|
||||
Var *vp;
|
||||
Chan *cp;
|
||||
int ef_num;
|
||||
extern int num_channels;
|
||||
extern Var *var_list;
|
||||
extern Chan *chan_list;
|
||||
Var *vp;
|
||||
Chan *cp;
|
||||
extern int num_events;
|
||||
int n;
|
||||
|
||||
ef_num = num_channels + 1; /* start with 1-st avail mask bit */
|
||||
/* Assign event flag numbers (starting at 1) */
|
||||
printf("\n/* Event flags */\n");
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "\nAssign values to event flags\n");
|
||||
#endif
|
||||
num_events = 0;
|
||||
for (vp = var_list; vp != NULL; vp = vp->next)
|
||||
{
|
||||
cp = vp->chan;
|
||||
/* First see if this is an event flag */
|
||||
if (vp->type == V_EVFLAG)
|
||||
{
|
||||
if (cp != 0)
|
||||
vp->ef_num = cp->index + 1; /* sync'ed */
|
||||
else
|
||||
vp->ef_num = ef_num++;
|
||||
printf("#define %s\t%d\n", vp->name, vp->ef_num);
|
||||
num_events++;
|
||||
vp->ef_num = num_events;
|
||||
printf("#define %s\t%d\n", vp->name, num_events);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (cp != 0)
|
||||
vp->ef_num = cp->index + 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "%s: ef_num=%d\n", vp->name, vp->ef_num);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -387,6 +430,9 @@ assign_delay_ids()
|
||||
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)
|
||||
@@ -398,6 +444,10 @@ assign_delay_ids()
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -409,9 +459,10 @@ int *delay_id;
|
||||
ep->right = (Expr *)*delay_id;
|
||||
*delay_id += 1;
|
||||
}
|
||||
|
||||
/* Traverse the expression tree, and call the supplied
|
||||
* function on matched conditions */
|
||||
/* 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 */
|
||||
@@ -430,8 +481,7 @@ void *argp; /* ptr to argument to pass on to function */
|
||||
stype[ep->type], ep->value);
|
||||
|
||||
/* Call the function? */
|
||||
if ((ep->type == type) &&
|
||||
(value == 0 || strcmp(ep->value, value) == 0) )
|
||||
if ((ep->type == type) && (value == 0 || strcmp(ep->value, value) == 0) )
|
||||
{
|
||||
funcp(ep, argp);
|
||||
}
|
||||
@@ -439,7 +489,6 @@ void *argp; /* ptr to argument to pass on to function */
|
||||
/* Continue traversing the expression tree */
|
||||
switch(ep->type)
|
||||
{
|
||||
case E_EMPTY:
|
||||
case E_VAR:
|
||||
case E_CONST:
|
||||
case E_STRING:
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/* $Id$
|
||||
/*
|
||||
seq_ca.c,v 1.2 1995/06/27 15:25:54 wright Exp
|
||||
|
||||
* DESCRIPTION: Channel access interface for sequencer.
|
||||
*
|
||||
* Author: Andy Kozubal
|
||||
@@ -6,7 +8,7 @@
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* 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:
|
||||
@@ -37,16 +39,23 @@
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define ANSI
|
||||
#include "seq.h"
|
||||
#include <string.h>
|
||||
|
||||
LOCAL VOID *getPtrToValue(union db_access_val *, chtype);
|
||||
LOCAL VOID proc_db_events(union db_access_val *, CHAN *, int);
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#undef LOCAL
|
||||
#define LOCAL
|
||||
#endif DEBUG
|
||||
/*
|
||||
* seq_connect() - Connect to all database channels through channel access.
|
||||
*/
|
||||
@@ -58,21 +67,22 @@ SPROG *pSP;
|
||||
extern VOID seq_conn_handler();
|
||||
extern int seqInitialTaskId;
|
||||
|
||||
pSP->conn_count = 0;
|
||||
|
||||
/*
|
||||
* For each channel: substitute macros, connect to db,
|
||||
* & isssue monitor (if monitor request flaf is TRUE).
|
||||
* For each channel: connect to db & isssue monitor (if monFlag is TRUE).
|
||||
*/
|
||||
pDB = pSP->channels;
|
||||
for (i = 0; i < pSP->nchan; i++)
|
||||
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
|
||||
printf("connect to \"%s\"\n", pDB->db_name);
|
||||
#endif /* DEBUG */
|
||||
logMsg("seq_connect: connect %s to %s\n",
|
||||
pDB->pVarName, pDB->dbName);
|
||||
#endif DEBUG
|
||||
/* Connect to it */
|
||||
status = ca_build_and_connect(
|
||||
pDB->db_name, /* DB channel name */
|
||||
pDB->dbName, /* DB channel name */
|
||||
TYPENOTCONN, /* Don't get initial value */
|
||||
0, /* get count (n/a) */
|
||||
&(pDB->chid), /* ptr to chid */
|
||||
@@ -91,16 +101,19 @@ SPROG *pSP;
|
||||
/*
|
||||
* Issue monitor request
|
||||
*/
|
||||
if (pDB->mon_flag)
|
||||
if (pDB->monFlag)
|
||||
{
|
||||
seq_pvMonitor(pSP, 0, pDB);
|
||||
seq_pvMonitor((SS_ID)pSP->pSS, i);
|
||||
}
|
||||
pDB++;
|
||||
}
|
||||
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 *).
|
||||
@@ -108,33 +121,75 @@ SPROG *pSP;
|
||||
VOID seq_event_handler(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
SPROG *pSP;
|
||||
CHAN *pDB;
|
||||
struct dbr_sts_char *dbr_sts_ptr;
|
||||
void *pVal;
|
||||
int i, nbytes;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
pDB = (CHAN *)args.usr;
|
||||
|
||||
/* Copy value returned into user variable */
|
||||
pVal = getPtrToValue((union db_access_val *)args.dbr, pDB->get_type);
|
||||
nbytes = pDB->size * pDB->count;
|
||||
memcpy(pDB->var, pVal, nbytes);
|
||||
|
||||
/* Copy status & severity */
|
||||
dbr_sts_ptr = (struct dbr_sts_char *)args.dbr;
|
||||
pDB->status = dbr_sts_ptr->status;
|
||||
pDB->severity = dbr_sts_ptr->severity;
|
||||
|
||||
/* Process event handling in each state set */
|
||||
pSP = pDB->sprog; /* State program that owns this db entry */
|
||||
|
||||
/* Wake up each state set that is waiting for event processing */
|
||||
seq_efSet(pSP, 0, pDB->index + 1);
|
||||
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(args)
|
||||
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(pAccess, pDB, complete_type)
|
||||
union db_access_val *pAccess;
|
||||
CHAN *pDB;
|
||||
int complete_type;
|
||||
{
|
||||
SPROG *pSP;
|
||||
void *pVal;
|
||||
int i;
|
||||
|
||||
#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 *)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;
|
||||
|
||||
/* 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 pvGet() */
|
||||
if (complete_type == GET_COMPLETE)
|
||||
{
|
||||
pDB->getComplete = TRUE;
|
||||
|
||||
/* If syncronous pvGet then notify pending state set */
|
||||
if (pDB->getSemId != NULL)
|
||||
semGive(pDB->getSemId);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disconnect all database channels */
|
||||
seq_disconnect(pSP)
|
||||
SPROG *pSP;
|
||||
@@ -143,43 +198,54 @@ SPROG *pSP;
|
||||
STATUS status;
|
||||
int i;
|
||||
extern int seqAuxTaskId;
|
||||
SPROG *pMySP; /* NULL if this task is not a sequencer task */
|
||||
|
||||
/* Did we already disconnect? */
|
||||
if (pSP->conn_count < 0)
|
||||
if (pSP->connCount < 0)
|
||||
return 0;
|
||||
|
||||
/* Import Channel Access context from the auxillary seq. task */
|
||||
ca_import(seqAuxTaskId);
|
||||
|
||||
pDB = pSP->channels;
|
||||
for (i = 0; i < pSP->nchan; i++)
|
||||
pMySP = seqFindProg(taskIdSelf() );
|
||||
if (pMySP == NULL)
|
||||
{
|
||||
ca_import(seqAuxTaskId); /* not a sequencer task */
|
||||
}
|
||||
|
||||
pDB = pSP->pChan;
|
||||
for (i = 0; i < pSP->numChans; i++, pDB++)
|
||||
{
|
||||
if (!pDB->assigned)
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
printf("disconnect \"%s\"\n", pDB->db_name);
|
||||
#endif /* DEBUG */
|
||||
logMsg("seq_disconnect: disconnect %s from %s\n",
|
||||
pDB->pVarName, pDB->dbName);
|
||||
taskDelay(30);
|
||||
#endif DEBUG
|
||||
/* Disconnect this channel */
|
||||
status = ca_clear_channel(pDB->chid);
|
||||
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
SEVCHK(status, "ca_clear_chan");
|
||||
ca_task_exit();
|
||||
return -1;
|
||||
/* SEVCHK(status, "ca_clear_chan"); */
|
||||
/* ca_task_exit(); */
|
||||
/* return -1; */
|
||||
}
|
||||
|
||||
/* Clear monitor & connect indicators */
|
||||
pDB->monitored = FALSE;
|
||||
pDB->connected = FALSE;
|
||||
|
||||
pDB++;
|
||||
}
|
||||
|
||||
pSP->conn_count = -1; /* flag to indicate all disconnected */
|
||||
pSP->connCount = -1; /* flag to indicate all disconnected */
|
||||
|
||||
ca_flush_io();
|
||||
|
||||
/* Cancel CA import */
|
||||
ca_import_cancel(taskIdSelf());
|
||||
/* Cancel CA context if it was imported above */
|
||||
if (pMySP == NULL)
|
||||
{
|
||||
logMsg("seq_disconnect: cancel import CA context\n");
|
||||
ca_import_cancel(taskIdSelf());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -204,309 +270,55 @@ struct connection_handler_args args;
|
||||
if (ca_field_type(args.chid) == TYPENOTCONN)
|
||||
{
|
||||
pDB->connected = FALSE;
|
||||
pSP->conn_count--;
|
||||
pSP->connCount--;
|
||||
pDB->monitored = FALSE;
|
||||
#ifdef DEBUG
|
||||
seq_log(pSP, "Channel \"%s\" disconnected\n", pDB->db_name);
|
||||
#endif /* DEBUG */
|
||||
logMsg("%s disconnected from %s\n", pDB->VarName, pDB->dbName);
|
||||
#endif DEBUG
|
||||
}
|
||||
else
|
||||
else /* PV connected */
|
||||
{
|
||||
pDB->connected = TRUE;
|
||||
pSP->conn_count++;
|
||||
pSP->connCount++;
|
||||
if (pDB->monFlag)
|
||||
pDB->monitored = TRUE;
|
||||
#ifdef DEBUG
|
||||
seq_log(pSP, "Channel \"%s\" connected\n", pDB->db_name);
|
||||
#endif /* DEBUG */
|
||||
if (pDB->count > ca_element_count(args.chid))
|
||||
{
|
||||
pDB->count = ca_element_count(args.chid);
|
||||
#ifdef DEBUG
|
||||
seq_log(pSP, "\"%s\": reset count to %d\n",
|
||||
pDB->db_name, pDB->count);
|
||||
#endif /* 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 */
|
||||
seq_efSet(pSP, 0, 0);
|
||||
seqWakeup(pSP, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_efSet() - Set an event flag, then wake up each state
|
||||
* set that might be waiting on that event flag.
|
||||
* 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 seq_efSet(pSP, dummy, ev_flag)
|
||||
VOID seqWakeup(pSP, eventNum)
|
||||
SPROG *pSP;
|
||||
int dummy;
|
||||
int ev_flag; /* event flag */
|
||||
int eventNum;
|
||||
{
|
||||
SSCB *pSS;
|
||||
int nss;
|
||||
SSCB *pSS;
|
||||
|
||||
/* Set this bit (apply resource lock) */
|
||||
semTake(pSP->caSemId, WAIT_FOREVER);
|
||||
bitSet(pSP->events, ev_flag);
|
||||
|
||||
/* Check flag against mask for all state sets: */
|
||||
for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++)
|
||||
/* Check event number against mask for all state sets: */
|
||||
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
|
||||
{
|
||||
/* Test for possible event trig based on bit mask for this state */
|
||||
if ( (ev_flag == 0) || bitTest(pSS->pMask, ev_flag) )
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Unlock resource */
|
||||
semGive(pSP->caSemId);
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_efTest() - Test event flag against outstanding events.
|
||||
*/
|
||||
int seq_efTest(pSP, pSS, ev_flag)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
return bitTest(pSP->events, ev_flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_efClear() - Test event flag against outstanding events, then clear it.
|
||||
*/
|
||||
int seq_efClear(pSP, pSS, ev_flag)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
int isSet;
|
||||
|
||||
isSet = bitTest(pSP->events, ev_flag);
|
||||
bitClear(pSP->events, ev_flag);
|
||||
return isSet;
|
||||
}
|
||||
/*
|
||||
* seq_pvGet() - Get DB value (uses channel access).
|
||||
*/
|
||||
seq_pvGet(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status, sem_status;
|
||||
extern VOID seq_callback_handler();
|
||||
|
||||
/* Check for channel connected */
|
||||
if (!pDB->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
/* Flag this pvGet() as not completed */
|
||||
pDB->get_complete = FALSE;
|
||||
|
||||
/* If synchronous pvGet then clear the pvGet pend semaphore */
|
||||
if ( !(pSP->options & OPT_ASYNC) )
|
||||
{
|
||||
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->get_type, /* db request type */
|
||||
pDB->count, /* element count */
|
||||
pDB->chid, /* chid */
|
||||
seq_callback_handler, /* callback handler */
|
||||
pDB); /* user arg */
|
||||
|
||||
if ( (pSP->options & OPT_ASYNC) || (status != ECA_NORMAL) )
|
||||
return status;
|
||||
|
||||
/* Synchronous pvGet() */
|
||||
|
||||
ca_flush_io();
|
||||
|
||||
/* Wait for completion (10s timeout) */
|
||||
sem_status = semTake(pSS->getSemId, 600);
|
||||
if (sem_status == ERROR)
|
||||
status = ECA_TIMEOUT;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(args)
|
||||
struct event_handler_args args;
|
||||
{
|
||||
SPROG *pSP;
|
||||
CHAN *pDB;
|
||||
struct dbr_sts_char *dbr_sts_ptr;
|
||||
int i, nbytes;
|
||||
void *pVal;
|
||||
|
||||
/* User arg is ptr to db channel structure */
|
||||
pDB = (CHAN *)args.usr;
|
||||
|
||||
/* Copy value returned into user variable */
|
||||
pVal = getPtrToValue((union db_access_val *)args.dbr, pDB->get_type);
|
||||
nbytes = pDB->size * pDB->count;
|
||||
memcpy(pDB->var, pVal, nbytes);
|
||||
|
||||
/* Copy status & severity */
|
||||
dbr_sts_ptr = (struct dbr_sts_char *)args.dbr;
|
||||
pDB->status = dbr_sts_ptr->status;
|
||||
pDB->severity = dbr_sts_ptr->severity;
|
||||
|
||||
/* Set get complete flag */
|
||||
pDB->get_complete = TRUE;
|
||||
|
||||
/* Wake up each state set that is waiting for event processing) */
|
||||
pSP = pDB->sprog; /* State program that owns this db entry */
|
||||
seq_efSet(pSP, 0, pDB->index + 1);
|
||||
|
||||
/* If syncronous pvGet then notify pending state set */
|
||||
if ( !(pSP->options & OPT_ASYNC) )
|
||||
semGive(pDB->getSemId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Flush outstanding CA requests */
|
||||
VOID seq_pvFlush()
|
||||
{
|
||||
ca_flush_io();
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvPut() - Put DB value (uses channel access).
|
||||
*/
|
||||
seq_pvPut(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
if (!pDB->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
status = ca_array_put(pDB->put_type, pDB->count,
|
||||
pDB->chid, pDB->var);
|
||||
if (status != ECA_NORMAL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
seq_log(pSP, "pvPut on \"%s\" failed (%d)\n",
|
||||
pDB->db_name, status);
|
||||
seq_log(pSP, " put_type=%d\n", pDB->put_type);
|
||||
seq_log(pSP, " size=%d, count=%d\n", pDB->size, pDB->count);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
/*
|
||||
* seq_pvMonitor() - Initiate a monitor on a channel.
|
||||
*/
|
||||
seq_pvMonitor(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
extern VOID seq_event_handler();
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("monitor \"%s\"\n", pDB->db_name);
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (pDB->monitored)
|
||||
return;
|
||||
|
||||
status = ca_add_array_event(
|
||||
pDB->get_type, /* requested type */
|
||||
pDB->count, /* element count */
|
||||
pDB->chid, /* chid */
|
||||
seq_event_handler, /* function to call */
|
||||
pDB, /* user arg (db struct) */
|
||||
pDB->delta, /* pos. delta value */
|
||||
pDB->delta, /* neg. delta value */
|
||||
pDB->timeout, /* 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;
|
||||
}
|
||||
ca_flush_io();
|
||||
|
||||
pDB->monitored = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvStopMonitor() - Cancel a monitor
|
||||
*/
|
||||
seq_pvStopMonitor(pSP, pSS, pDB)
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
SSCB *pSS; /* ptr to current state set */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
{
|
||||
int status;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* getPtr() - Given ptr to value structure & type, return ptr to value.
|
||||
*/
|
||||
LOCAL VOID *getPtrToValue(pBuf, dbrType)
|
||||
union db_access_val *pBuf;
|
||||
chtype dbrType;
|
||||
{
|
||||
switch (dbrType) {
|
||||
case DBR_STRING: return (void *)pBuf->strval;
|
||||
case DBR_STS_STRING: return (void *)pBuf->sstrval.value;
|
||||
|
||||
case DBR_SHORT: return (void *)&pBuf->shrtval;
|
||||
case DBR_STS_SHORT: return (void *)&pBuf->sshrtval.value;
|
||||
|
||||
case DBR_FLOAT: return (void *)&pBuf->fltval;
|
||||
case DBR_STS_FLOAT: return (void *)&pBuf->sfltval.value;
|
||||
|
||||
case DBR_ENUM: return (void *)&pBuf->enmval;
|
||||
case DBR_STS_ENUM: return (void *)&pBuf->senmval.value;
|
||||
|
||||
case DBR_CHAR: return (void *)&pBuf->charval;
|
||||
case DBR_STS_CHAR: return (void *)&pBuf->schrval.value;
|
||||
|
||||
case DBR_LONG: return (void *)&pBuf->longval;
|
||||
case DBR_STS_LONG: return (void *)&pBuf->slngval.value;
|
||||
|
||||
case DBR_DOUBLE: return (void *)&pBuf->doubleval;
|
||||
case DBR_STS_DOUBLE: return (void *)&pBuf->sdblval.value;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
#include "memLib.h"
|
||||
#include "taskVarLib.h"
|
||||
#include "taskLib.h"
|
||||
@@ -524,7 +336,7 @@ chtype dbrType;
|
||||
* SEE ALSO: taskVarAdd(2), taskVarGet(2), taskVarSet(2)
|
||||
*/
|
||||
|
||||
LOCAL STATUS taskVarDelete (tid, pVar)
|
||||
LOCAL STATUS LtaskVarDelete (tid, pVar)
|
||||
int tid; /* task id whose task variable is to be retrieved */
|
||||
int *pVar; /* pointer to task variable to be removed from task */
|
||||
|
||||
@@ -571,7 +383,7 @@ int tid;
|
||||
extern int ca_static;
|
||||
int status;
|
||||
|
||||
status = taskVarDelete(tid, &ca_static);
|
||||
status = LtaskVarDelete(tid, &ca_static);
|
||||
if (status != OK)
|
||||
{
|
||||
logMsg("Seq: taskVarDelete failed for tid = 0x%x\n", tid);
|
||||
|
||||
616
src/sequencer/seq_if.c
Normal file
616
src/sequencer/seq_if.c
Normal file
@@ -0,0 +1,616 @@
|
||||
/*
|
||||
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:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#define ANSI
|
||||
#include "seq.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).
|
||||
*/
|
||||
seq_pvGet(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int 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) )
|
||||
{
|
||||
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 ( (pSP->options & OPT_ASYNC) || (status != ECA_NORMAL) )
|
||||
return status;
|
||||
|
||||
/* Synchronous pvGet() */
|
||||
|
||||
ca_flush_io();
|
||||
|
||||
/* Wait for completion (10s timeout) */
|
||||
sem_status = semTake(pSS->getSemId, 600);
|
||||
if (sem_status == ERROR)
|
||||
status = ECA_TIMEOUT;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvGetComplete() - returns TRUE if the last get completed.
|
||||
*/
|
||||
seq_pvGetComplete(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
pDB = pSP->pChan;
|
||||
return pDB->getComplete;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* seq_pvPut() - Put DB value.
|
||||
*/
|
||||
seq_pvPut(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
pDB = pSP->pChan + pvId;
|
||||
#ifdef DEBUG
|
||||
logMsg("seq_pvPut: pv name=%s, pVar=0x%x\n", pDB->dbName, pDB->pVar);
|
||||
#endif DEBUG
|
||||
|
||||
if (!pDB->connected)
|
||||
return ECA_DISCONN;
|
||||
|
||||
status = ca_array_put(pDB->putType, pDB->count,
|
||||
pDB->chid, pDB->pVar);
|
||||
#ifdef DEBUG
|
||||
logMsg("seq_pvPut: status=%d\n", status);
|
||||
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, pDB->count);
|
||||
}
|
||||
#endif DEBUG
|
||||
|
||||
return status;
|
||||
}
|
||||
/*
|
||||
* seq_pvAssign() - Assign/Connect to a channel.
|
||||
* Assign to a zero-lth string ("") disconnects/de-assignes.
|
||||
*/
|
||||
seq_pvAssign(ssId, pvId, pvName)
|
||||
SS_ID ssId;
|
||||
int 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.
|
||||
*/
|
||||
seq_pvMonitor(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int 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
|
||||
*/
|
||||
seq_pvStopMonitor(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int 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.
|
||||
*/
|
||||
seq_pvChannelCount(ssId)
|
||||
SS_ID ssId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
return pSP->numChans;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvConnectCount() - returns number of database channels connected.
|
||||
*/
|
||||
seq_pvConnectCount(ssId)
|
||||
SS_ID ssId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
return pSP->connCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvAssignCount() - returns number of database channels assigned.
|
||||
*/
|
||||
seq_pvAssignCount(ssId)
|
||||
SS_ID ssId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
return pSP->assignCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvConnected() - returns TRUE if database channel is connected.
|
||||
*/
|
||||
seq_pvConnected(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB;
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
pDB = pSP->pChan + pvId;
|
||||
return pDB->connected;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvAssigned() - returns TRUE if database channel is assigned.
|
||||
*/
|
||||
seq_pvAssigned(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB;
|
||||
int status;
|
||||
|
||||
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.
|
||||
*/
|
||||
seq_pvCount(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
pDB = pSP->pChan + pvId;
|
||||
return pDB->dbCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvStatus() - returns channel alarm status.
|
||||
*/
|
||||
seq_pvStatus(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
pDB = pSP->pChan + pvId;
|
||||
return pDB->status;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvSeverity() - returns channel alarm severity.
|
||||
*/
|
||||
seq_pvSeverity(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
int status;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
pDB = pSP->pChan + pvId;
|
||||
return pDB->severity;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvIndex() - returns index of database variable.
|
||||
*/
|
||||
int seq_pvIndex(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
return pvId; /* index is same as pvId */
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_pvTimeStamp() - returns channel time stamp.
|
||||
*/
|
||||
TS_STAMP seq_pvTimeStamp(ssId, pvId)
|
||||
SS_ID ssId;
|
||||
int pvId;
|
||||
{
|
||||
SPROG *pSP; /* ptr to state program */
|
||||
CHAN *pDB; /* ptr to channel struct */
|
||||
int status;
|
||||
|
||||
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(ssId, ev_flag)
|
||||
SS_ID ssId;
|
||||
int ev_flag; /* event flag */
|
||||
{
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int nss;
|
||||
|
||||
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);
|
||||
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.
|
||||
*/
|
||||
int seq_efTest(ssId, ev_flag)
|
||||
SS_ID ssId;
|
||||
int 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);
|
||||
#endif DEBUG
|
||||
return isSet;
|
||||
}
|
||||
|
||||
/*
|
||||
* seq_efClear() - Test event flag against outstanding events, then clear it.
|
||||
*/
|
||||
int seq_efClear(ssId, ev_flag)
|
||||
SS_ID ssId;
|
||||
int ev_flag; /* event 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.
|
||||
*/
|
||||
int seq_efTestAndClear(ssId, ev_flag)
|
||||
SS_ID ssId;
|
||||
int ev_flag; /* event 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 */
|
||||
int seq_delay(ssId, delayId)
|
||||
SS_ID ssId;
|
||||
int 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 on entering a state.
|
||||
*/
|
||||
VOID seq_delayInit(ssId, delayId, delay)
|
||||
SS_ID ssId;
|
||||
int delayId;
|
||||
float delay; /* delay in seconds */
|
||||
{
|
||||
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.
|
||||
* FALSE means "-" and TRUE means "+".
|
||||
*/
|
||||
BOOL seq_optGet(ssId, opt)
|
||||
SS_ID ssId;
|
||||
char *opt; /* one of the snc options as a strign (e.g. "a") */
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,9 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
|
||||
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.
|
||||
@@ -11,77 +13,72 @@
|
||||
ENVIRONMENT: VxWorks
|
||||
|
||||
HISTORY:
|
||||
01mar94,ajk Added seq_macValueGet() as state program interface routine.
|
||||
|
||||
***************************************************************************/
|
||||
#define ANSI
|
||||
#include "seq.h"
|
||||
#include <string.h>
|
||||
|
||||
LOCAL int macNameLth(char *);
|
||||
LOCAL int seqMacParseName(char *);
|
||||
LOCAL int seqMacParseValue(char *);
|
||||
LOCAL char *skipBlanks(char *);
|
||||
LOCAL MACRO *seqMacTblGet(char *, MACRO *);
|
||||
LOCAL MACRO *seqMacTblGet(MACRO *, char *);
|
||||
|
||||
/*#define DEBUG*/
|
||||
|
||||
/*
|
||||
*seqMacTblInit - initialize macro the table.
|
||||
*/
|
||||
seqMacTblInit(pMac)
|
||||
MACRO *pMac;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < MAX_MACROS; i++, pMac++)
|
||||
{
|
||||
pMac->name = NULL;
|
||||
pMac->value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*seqMacEval - substitute macro value into a string containing:
|
||||
* ....{mac_name}....
|
||||
*/
|
||||
seqMacEval(pInStr, pOutStr, maxChar, macTbl)
|
||||
VOID seqMacEval(pInStr, pOutStr, maxChar, pMac)
|
||||
char *pInStr;
|
||||
char *pOutStr;
|
||||
int maxChar;
|
||||
MACRO *macTbl;
|
||||
MACRO *pMac;
|
||||
{
|
||||
char *pMacVal, *pTmp;
|
||||
char name[50], *pValue, *pTmp;
|
||||
int nameLth, valLth;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("seqMacEval: InStr=%s\n", pInStr);
|
||||
logMsg("seqMacEval: InStr=%s\n", pInStr);
|
||||
taskDelay(30);
|
||||
#endif
|
||||
pTmp = pOutStr;
|
||||
while (*pInStr != 0 && maxChar > 0)
|
||||
{
|
||||
if (*pInStr == '{')
|
||||
{ /* Macro substitution */
|
||||
{ /* Do macro substitution */
|
||||
pInStr++; /* points to macro name */
|
||||
nameLth = macNameLth(pInStr);
|
||||
/* 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
|
||||
printf("Name=%s[%d]\n", pInStr, nameLth);
|
||||
logMsg("Macro name=%s\n", name);
|
||||
taskDelay(30);
|
||||
#endif
|
||||
/* Find macro value from macro name */
|
||||
pMacVal = seqMacValGet(pInStr, nameLth, macTbl);
|
||||
if (pMacVal != NULL)
|
||||
pValue = seqMacValGet(pMac, name);
|
||||
if (pValue != NULL)
|
||||
{ /* Substitute macro value */
|
||||
valLth = strlen(pMacVal);
|
||||
valLth = strlen(pValue);
|
||||
if (valLth > maxChar)
|
||||
valLth = maxChar;
|
||||
#ifdef DEBUG
|
||||
printf("Val=%s[%d]\n", pMacVal, valLth);
|
||||
logMsg("Value=%s\n", pValue);
|
||||
#endif
|
||||
strncpy(pOutStr, pMacVal, valLth);
|
||||
strncpy(pOutStr, pValue, valLth);
|
||||
maxChar -= valLth;
|
||||
pOutStr += valLth;
|
||||
}
|
||||
pInStr += nameLth;
|
||||
if (*pInStr != 0)
|
||||
pInStr++; /* skip '}' */
|
||||
|
||||
}
|
||||
else
|
||||
@@ -89,52 +86,58 @@ MACRO *macTbl;
|
||||
*pOutStr++ = *pInStr++;
|
||||
maxChar--;
|
||||
}
|
||||
*pOutStr = 0;
|
||||
#ifdef DEBUG
|
||||
printf("OutStr=%s\n", pTmp);
|
||||
#endif
|
||||
}
|
||||
*pOutStr = 0;
|
||||
#ifdef DEBUG
|
||||
logMsg("OutStr=%s\n", pTmp);
|
||||
taskDelay(30);
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* seqMacValGet - given macro name, return pointer to its value.
|
||||
* seq_macValueGet - given macro name, return pointer to its value.
|
||||
*/
|
||||
char *seqMacValGet(macName, macNameLth, macTbl)
|
||||
char *macName;
|
||||
int macNameLth;
|
||||
MACRO *macTbl;
|
||||
char *seq_macValueGet(ssId, pName)
|
||||
SS_ID ssId;
|
||||
char *pName;
|
||||
{
|
||||
int i;
|
||||
SPROG *pSP;
|
||||
MACRO *pMac;
|
||||
|
||||
for (i = 0 ; i < MAX_MACROS; i++, macTbl++)
|
||||
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 ((macTbl->name != NULL) &&
|
||||
(strlen(macTbl->name) == macNameLth))
|
||||
if (pMac->pName != NULL)
|
||||
{
|
||||
if (strncmp(macName, macTbl->name, macNameLth) == 0)
|
||||
if (strcmp(pName, pMac->pName) == 0)
|
||||
{
|
||||
return macTbl->value;
|
||||
#ifdef DEBUG
|
||||
logMsg(", value=%s\n", pMac->pValue);
|
||||
#endif DEBUG
|
||||
return pMac->pValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
logMsg(", no value\n");
|
||||
#endif DEBUG
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* macNameLth() - Return number of characters in a macro name */
|
||||
LOCAL int macNameLth(pstr)
|
||||
char *pstr;
|
||||
{
|
||||
int nchar;
|
||||
|
||||
nchar = 0;
|
||||
while ( (*pstr != 0) && (*pstr != '}') )
|
||||
{
|
||||
pstr++;
|
||||
nchar++;
|
||||
}
|
||||
return nchar;
|
||||
}
|
||||
/*
|
||||
* seqMacParse - parse the macro definition string and build
|
||||
* the macro table (name/value pairs). Returns number of macros parsed.
|
||||
@@ -147,11 +150,11 @@ SPROG *pSP;
|
||||
{
|
||||
int nMac, nChar;
|
||||
char *skipBlanks();
|
||||
MACRO *macTbl; /* macro table */
|
||||
MACRO *pMac; /* macro table */
|
||||
MACRO *pMacTbl; /* macro tbl entry */
|
||||
char *name, *value;
|
||||
char *pName, *pValue;
|
||||
|
||||
macTbl = pSP->mac_ptr;
|
||||
pMac = pSP->pMacros;
|
||||
for ( ;; )
|
||||
{
|
||||
/* Skip blanks */
|
||||
@@ -162,23 +165,24 @@ SPROG *pSP;
|
||||
nChar = seqMacParseName(pMacStr);
|
||||
if (nChar == 0)
|
||||
break; /* finished or error */
|
||||
name = seqAlloc(pSP, nChar+1);
|
||||
if (name == NULL)
|
||||
pName = (char *)calloc(nChar+1, 1);
|
||||
if (pName == NULL)
|
||||
break;
|
||||
memcpy(name, pMacStr, nChar);
|
||||
name[nChar] = 0;
|
||||
bcopy(pMacStr, pName, nChar);
|
||||
pName[nChar] = 0;
|
||||
#ifdef DEBUG
|
||||
printf("name=%s, nChar=%d\n", name, nChar);
|
||||
logMsg("name=%s, nChar=%d\n", pName, nChar);
|
||||
taskDelay(30);
|
||||
#endif
|
||||
pMacStr += nChar;
|
||||
|
||||
/* Find a slot in the table */
|
||||
pMacTbl = seqMacTblGet(name, macTbl);
|
||||
pMacTbl = seqMacTblGet(pMac, pName);
|
||||
if (pMacTbl == NULL)
|
||||
break; /* table is full */
|
||||
if (pMacTbl->name == NULL)
|
||||
if (pMacTbl->pName == NULL)
|
||||
{ /* Empty slot, insert macro name */
|
||||
pMacTbl->name = name;
|
||||
pMacTbl->pName = pName;
|
||||
}
|
||||
|
||||
/* Skip over blanks and equal sign or comma */
|
||||
@@ -196,20 +200,26 @@ SPROG *pSP;
|
||||
nChar = seqMacParseValue(pMacStr);
|
||||
if (nChar == 0)
|
||||
break;
|
||||
value = seqAlloc(pSP, nChar+1);
|
||||
if (value == NULL)
|
||||
|
||||
/* 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;
|
||||
memcpy(value, pMacStr, nChar);
|
||||
value[nChar] = 0;
|
||||
pMacStr += nChar;
|
||||
pMacTbl->pValue = pValue;
|
||||
bcopy(pMacStr, pValue, nChar);
|
||||
pValue[nChar] = 0;
|
||||
#ifdef DEBUG
|
||||
printf("value=%s, nChar=%d\n", value, nChar);
|
||||
logMsg("value=%s, nChar=%d\n", pValue, nChar);
|
||||
taskDelay(30);
|
||||
#endif
|
||||
|
||||
/* Insert or replace macro value */
|
||||
pMacTbl->value = value;
|
||||
|
||||
/* Skip blanks and comma */
|
||||
/* Skip past last value and over blanks and comma */
|
||||
pMacStr += nChar;
|
||||
pMacStr = skipBlanks(pMacStr);
|
||||
if (*pMacStr++ != ',')
|
||||
break;
|
||||
@@ -245,7 +255,8 @@ char *pStr;
|
||||
|
||||
/*
|
||||
* seqMacParseValue() - Parse a macro value from the input string.
|
||||
*/LOCAL int seqMacParseValue(pStr)
|
||||
*/
|
||||
LOCAL int seqMacParseValue(pStr)
|
||||
char *pStr;
|
||||
{
|
||||
int nChar;
|
||||
@@ -260,6 +271,7 @@ char *pStr;
|
||||
return nChar;
|
||||
}
|
||||
|
||||
/* skipBlanks() - skip blank characters */
|
||||
LOCAL char *skipBlanks(pChar)
|
||||
char *pChar;
|
||||
{
|
||||
@@ -272,21 +284,22 @@ char *pChar;
|
||||
* seqMacTblGet - find a match for the specified name, otherwise
|
||||
* return an empty slot in macro table.
|
||||
*/
|
||||
LOCAL MACRO *seqMacTblGet(name, macTbl)
|
||||
char *name; /* macro name */
|
||||
MACRO *macTbl;
|
||||
LOCAL MACRO *seqMacTblGet(pMac, pName)
|
||||
MACRO *pMac;
|
||||
char *pName; /* macro name */
|
||||
{
|
||||
int i;
|
||||
MACRO *pMacTbl;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("seqMacTblGet: name=%s\n", name);
|
||||
logMsg("seqMacTblGet: name=%s\n", pName);
|
||||
taskDelay(30);
|
||||
#endif
|
||||
for (i = 0, pMacTbl = macTbl; i < MAX_MACROS; i++, pMacTbl++)
|
||||
for (i = 0, pMacTbl = pMac; i < MAX_MACROS; i++, pMacTbl++)
|
||||
{
|
||||
if (pMacTbl->name != NULL)
|
||||
if (pMacTbl->pName != NULL)
|
||||
{
|
||||
if (strcmp(name, pMacTbl->name) == 0)
|
||||
if (strcmp(pName, pMacTbl->pName) == 0)
|
||||
{
|
||||
return pMacTbl;
|
||||
}
|
||||
@@ -294,9 +307,9 @@ MACRO *macTbl;
|
||||
}
|
||||
|
||||
/* Not found, find an empty slot */
|
||||
for (i = 0, pMacTbl = macTbl; i < MAX_MACROS; i++, pMacTbl++)
|
||||
for (i = 0, pMacTbl = pMac; i < MAX_MACROS; i++, pMacTbl++)
|
||||
{
|
||||
if (pMacTbl->name == NULL)
|
||||
if (pMacTbl->pName == NULL)
|
||||
{
|
||||
return pMacTbl;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, 91, 92, 93, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
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
|
||||
|
||||
$Id$
|
||||
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
|
||||
@@ -30,25 +32,41 @@
|
||||
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 task for channel access, all state programs.
|
||||
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.
|
||||
***************************************************************************/
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#include "seqCom.h"
|
||||
#include "seq.h"
|
||||
#ifdef DEBUG
|
||||
#undef LOCAL
|
||||
#define LOCAL
|
||||
#endif DEBUG
|
||||
|
||||
/* ANSI functional prototypes for local routines */
|
||||
LOCAL SPROG *alloc_task_area(SPROG *);
|
||||
LOCAL VOID copy_sprog(SPROG *, SPROG *);
|
||||
LOCAL VOID init_sprog(SPROG *);
|
||||
LOCAL VOID init_sscb(SPROG *);
|
||||
LOCAL SPROG *seqInitTables(struct seqProgram *);
|
||||
LOCAL SPROG *alloc_task_area(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 int countStates(struct seqProgram *);
|
||||
LOCAL int roundUp(int);
|
||||
LOCAL VOID selectDBtype(char *, short *, short *, short *, short *);
|
||||
|
||||
#define SCRATCH_SIZE (MAX_MACROS*(MAX_STRING_SIZE+1)*12)
|
||||
/* Globals */
|
||||
@@ -68,41 +86,22 @@ int seqAuxTaskId = 0;
|
||||
* Creates the initial state program task and returns its task id.
|
||||
* Most initialization is performed here.
|
||||
*/
|
||||
int seq(pSP_orig, macro_def, stack_size)
|
||||
SPROG *pSP_orig; /* ptr to original state program table */
|
||||
char *macro_def; /* optional macro def'n string */
|
||||
int stack_size; /* optional stack size (bytes) */
|
||||
int seq(pSeqProg, macro_def, stack_size)
|
||||
struct seqProgram *pSeqProg; /* state program info generated by snc */
|
||||
char *macro_def; /* optional macro def'n string */
|
||||
int stack_size; /* optional stack size (bytes) */
|
||||
{
|
||||
int tid;
|
||||
extern sequencer(); /* Sequencer task entry point */
|
||||
extern sprog_delete(); /* Task delete routine */
|
||||
extern char *seqVersion;
|
||||
SPROG *pSP, *alloc_task_area();
|
||||
char *pname, *pvalue, *ptask_name;
|
||||
SPROG *pSP;
|
||||
char *pValue, *ptask_name;
|
||||
extern seqAuxTask();
|
||||
|
||||
/* Print version & date of sequencer */
|
||||
printf("%s\n", seqVersion);
|
||||
|
||||
/* Exit if no parameters specified */
|
||||
if (pSP_orig == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for correct state program format */
|
||||
if (pSP_orig->magic != MAGIC)
|
||||
{ /* Oops */
|
||||
logMsg("Illegal magic number in state program.\n");
|
||||
logMsg(" - Possible mismatch between SNC & SEQ versions\n");
|
||||
logMsg(" - Re-compile your program?\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
print_sp_info(pSP_orig);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* Spawn the sequencer auxillary task */
|
||||
if (seqAuxTaskId == 0)
|
||||
{
|
||||
@@ -110,6 +109,9 @@ int stack_size; /* optional stack size (bytes) */
|
||||
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);
|
||||
#endif DEBUG
|
||||
}
|
||||
|
||||
/* Specify a routine to run at task delete */
|
||||
@@ -119,23 +121,26 @@ int stack_size; /* optional stack size (bytes) */
|
||||
seqDeleteHookAdded = TRUE;
|
||||
}
|
||||
|
||||
/* Allocate a contiguous space for all dynamic structures */
|
||||
pSP = alloc_task_area(pSP_orig);
|
||||
/* Exit if no parameters specified */
|
||||
if (pSeqProg == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make a private copy of original structures (but change pointers!) */
|
||||
copy_sprog(pSP_orig, pSP);
|
||||
/* Check for correct state program format */
|
||||
if (pSeqProg->magic != MAGIC)
|
||||
{ /* Oops */
|
||||
logMsg("Illegal magic number in state program.\n");
|
||||
logMsg(" - Possible mismatch between SNC & SEQ versions\n");
|
||||
logMsg(" - Re-compile your program?\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize state program block */
|
||||
init_sprog(pSP);
|
||||
|
||||
/* Initialize state set control blocks */
|
||||
init_sscb(pSP);
|
||||
|
||||
/* Initialize the macro definition table */
|
||||
seqMacTblInit(pSP->mac_ptr); /* Init macro table */
|
||||
/* Initialize the sequencer tables */
|
||||
pSP = seqInitTables(pSeqProg);
|
||||
|
||||
/* Parse the macro definitions from the "program" statement */
|
||||
seqMacParse(pSP->params, pSP);
|
||||
seqMacParse(pSeqProg->pParams, pSP);
|
||||
|
||||
/* Parse the macro definitions from the command line */
|
||||
seqMacParse(macro_def, pSP);
|
||||
@@ -149,183 +154,99 @@ int stack_size; /* optional stack size (bytes) */
|
||||
/* Specify stack size */
|
||||
if (stack_size == 0)
|
||||
stack_size = SPAWN_STACK_SIZE;
|
||||
pname = "stack";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), pSP->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
pValue = seqMacValGet(pSP->pMacros, "stack");
|
||||
if (pValue != NULL && strlen(pValue) > 0)
|
||||
{
|
||||
sscanf(pvalue, "%d", &stack_size);
|
||||
sscanf(pValue, "%d", &stack_size);
|
||||
}
|
||||
if (stack_size < SPAWN_STACK_SIZE/2)
|
||||
stack_size = SPAWN_STACK_SIZE/2;
|
||||
|
||||
/* Specify task name */
|
||||
pname = "name";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), pSP->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
ptask_name = pvalue;
|
||||
pValue = seqMacValGet(pSP->pMacros, "name");
|
||||
if (pValue != NULL && strlen(pValue) > 0)
|
||||
ptask_name = pValue;
|
||||
else
|
||||
ptask_name = pSP->name;
|
||||
ptask_name = pSP->pProgName;
|
||||
|
||||
/* Spawn the initial sequencer task */
|
||||
#ifdef DEBUG
|
||||
logMsg("Spawing task %s, stack_size=%d\n", ptask_name, stack_size);
|
||||
#endif
|
||||
tid = taskSpawn(ptask_name, SPAWN_PRIORITY, SPAWN_OPTIONS,
|
||||
stack_size, 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->name, ptask_name);
|
||||
pSP->pProgName, ptask_name);
|
||||
seq_log(pSP, " Task id = %d = 0x%x\n", tid, tid);
|
||||
|
||||
/* Return task id to calling program */
|
||||
return tid;
|
||||
}
|
||||
|
||||
/*
|
||||
* ALLOC_TASK_AREA
|
||||
* Allocate a single block for all dynamic structures
|
||||
* The pointer to the allocated area is saved for task delete hook routine.
|
||||
*/
|
||||
LOCAL SPROG *alloc_task_area(pSP_orig)
|
||||
SPROG *pSP_orig; /* original state program structure */
|
||||
/* seqInitTables - initialize sequencer tables */
|
||||
LOCAL SPROG *seqInitTables(pSeqProg)
|
||||
struct seqProgram *pSeqProg;
|
||||
{
|
||||
int size, nss, nstates, nchannels, user_size,
|
||||
prog_size, ss_size, state_size, chan_size, mac_size, scr_size;
|
||||
SPROG *pSP_new; /* ptr to new state program struct */
|
||||
char *dyn_ptr, *dyn_ptr_start; /* ptr to allocated area */
|
||||
SPROG *pSP;
|
||||
|
||||
nss = pSP_orig->nss;
|
||||
nstates = pSP_orig->nstates;
|
||||
nchannels = pSP_orig->nchan;
|
||||
pSP = (SPROG *)calloc(1, sizeof (SPROG));
|
||||
|
||||
/* Calc. # of bytes to allocate for all structures */
|
||||
prog_size = sizeof(SPROG);
|
||||
ss_size = nss*sizeof(SSCB);
|
||||
state_size = nstates*sizeof(STATE);
|
||||
chan_size = nchannels*sizeof(CHAN);
|
||||
user_size = pSP_orig->user_size;
|
||||
mac_size = MAX_MACROS*sizeof(MACRO);
|
||||
scr_size = SCRATCH_SIZE;
|
||||
/* Initialize state program block */
|
||||
init_sprog(pSeqProg, pSP);
|
||||
|
||||
/* Total # bytes to allocate */
|
||||
size = prog_size + ss_size + state_size +
|
||||
chan_size + user_size + mac_size + scr_size;
|
||||
/* Initialize state set control blocks */
|
||||
init_sscb(pSeqProg, pSP);
|
||||
|
||||
/* Alloc the dynamic task area */
|
||||
dyn_ptr = dyn_ptr_start = (char *)calloc(size, 1);
|
||||
/* Initialize database channel blocks */
|
||||
init_chan(pSeqProg, pSP);
|
||||
|
||||
/* Initialize the macro table */
|
||||
init_mac(pSP);
|
||||
|
||||
|
||||
return pSP;
|
||||
}
|
||||
|
||||
/* Count the total number of states in a state program */
|
||||
LOCAL int countStates(pSeqProg)
|
||||
struct seqProgram *pSeqProg;
|
||||
{
|
||||
struct seqSS *pSeqSS;
|
||||
int nstates, nss;
|
||||
|
||||
nstates = 0;
|
||||
for (nss = 0, pSeqSS = pSeqProg->pSS; nss < pSeqProg->numSS; nss++, pSeqSS++)
|
||||
nstates += pSeqSS->numStates;
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
{
|
||||
SSCB *pSS;
|
||||
STATE *pState;
|
||||
CHAN *pDB;
|
||||
char *pVar;
|
||||
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 = pSeqProg->exitFunc;
|
||||
pSP->varSize = pSeqProg->varSize;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Allocate task area:\n");
|
||||
printf(" nss=%d, nstates=%d, nchannels=%d\n", nss, nstates, nchannels);
|
||||
printf(" prog_size=%d, ss_size=%d, state_size=%d\n",
|
||||
prog_size, ss_size, state_size);
|
||||
printf(" user_size=%d, mac_size=%d, scr_size=%d\n",
|
||||
user_size, mac_size, scr_size);
|
||||
printf(" size=%d=0x%x\n", size, size);
|
||||
printf(" dyn_ptr=%d=0x%x\n", dyn_ptr, dyn_ptr);
|
||||
#endif /* DEBUG */
|
||||
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
|
||||
|
||||
/* Set ptrs in the PROG structure */
|
||||
pSP_new = (SPROG *)dyn_ptr;
|
||||
|
||||
/* Copy the SPROG struct contents */
|
||||
*pSP_new = *pSP_orig;
|
||||
|
||||
/* Allocate space for copies of the original structures */
|
||||
dyn_ptr += prog_size;
|
||||
pSP_new->sscb = (SSCB *)dyn_ptr;
|
||||
dyn_ptr += ss_size;
|
||||
pSP_new->states = (STATE *)dyn_ptr;
|
||||
dyn_ptr += state_size;
|
||||
pSP_new->channels = (CHAN *)dyn_ptr;
|
||||
dyn_ptr += chan_size;
|
||||
if (user_size != 0)
|
||||
{
|
||||
pSP_new->user_area = (char *)dyn_ptr;
|
||||
dyn_ptr += user_size;
|
||||
}
|
||||
else
|
||||
pSP_new->user_area = NULL;
|
||||
|
||||
/* Create additional dynamic structures for macros and scratch area */
|
||||
pSP_new->mac_ptr = (MACRO *)dyn_ptr;
|
||||
dyn_ptr += mac_size;
|
||||
pSP_new->scr_ptr = (char *)dyn_ptr;
|
||||
pSP_new->scr_nleft = scr_size;
|
||||
|
||||
/* Save ptr to start of allocated area so we can free it at task delete */
|
||||
pSP_new->dyn_ptr = dyn_ptr_start;
|
||||
|
||||
return pSP_new;
|
||||
}
|
||||
/*
|
||||
* Copy the SSCB, STATE, and CHAN structures into this task's dynamic structures.
|
||||
* Note: we have to change some pointers in the SPROG struct, user variables,
|
||||
* and all SSCB structs.
|
||||
*/
|
||||
LOCAL VOID copy_sprog(pSP_orig, pSP)
|
||||
SPROG *pSP_orig; /* original ptr to program struct */
|
||||
SPROG *pSP; /* new ptr */
|
||||
{
|
||||
SSCB *pSS, *pSS_orig;
|
||||
STATE *pST, *pST_orig;
|
||||
CHAN *pDB, *pDB_orig;
|
||||
int nss, nstates, nchan;
|
||||
char *var_ptr;
|
||||
|
||||
/* Ptr to 1-st SSCB in original SPROG */
|
||||
pSS_orig = pSP_orig->sscb;
|
||||
|
||||
/* Ptr to 1-st SSCB in new SPROG */
|
||||
pSS = pSP->sscb;
|
||||
|
||||
/* Copy structures for each state set */
|
||||
for (nss = 0, pST = pSP->states; nss < pSP->nss; nss++)
|
||||
{
|
||||
*pSS = *pSS_orig; /* copy SSCB */
|
||||
pSS->states = pST; /* new ptr to 1-st STATE */
|
||||
pST_orig = pSS_orig->states;
|
||||
for (nstates = 0; nstates < pSS->num_states; nstates++)
|
||||
{
|
||||
*pST = *pST_orig; /* copy STATE struct */
|
||||
pST++;
|
||||
pST_orig++;
|
||||
}
|
||||
pSS++;
|
||||
pSS_orig++;
|
||||
}
|
||||
|
||||
/* Copy database channel structures */
|
||||
pDB = pSP->channels;
|
||||
pDB_orig = pSP_orig->channels;
|
||||
var_ptr = pSP->user_area;
|
||||
for (nchan = 0; nchan < pSP->nchan; nchan++)
|
||||
{
|
||||
*pDB = *pDB_orig;
|
||||
|
||||
/* Reset ptr to SPROG structure */
|
||||
pDB->sprog = pSP;
|
||||
|
||||
/* +r: Convert offset to address of the user variable.
|
||||
* -r: var_ptr is an absolute address.
|
||||
*/
|
||||
if (pSP->options & OPT_REENT)
|
||||
pDB->var += (int)var_ptr;
|
||||
|
||||
pDB++;
|
||||
pDB_orig++;
|
||||
}
|
||||
|
||||
/* Note: user area is not copied; it should be all zeros */
|
||||
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Initialize the state program block
|
||||
*/
|
||||
LOCAL VOID init_sprog(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Semaphore for resource locking on CA events */
|
||||
/* Create a semaphore for resource locking on CA events */
|
||||
pSP->caSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
|
||||
if (pSP->caSemId == NULL)
|
||||
{
|
||||
@@ -334,26 +255,54 @@ SPROG *pSP;
|
||||
}
|
||||
|
||||
pSP->task_is_deleted = FALSE;
|
||||
pSP->connCount = 0;
|
||||
pSP->assignCount = 0;
|
||||
pSP->logFd = 0;
|
||||
|
||||
/* Clear all event flags */
|
||||
for (i = 0; i < NWRDS; i++)
|
||||
pSP->events[i] = 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(pSP)
|
||||
SPROG *pSP;
|
||||
LOCAL VOID init_sscb(pSeqProg, pSP)
|
||||
struct seqProgram *pSeqProg;
|
||||
SPROG *pSP;
|
||||
{
|
||||
SSCB *pSS;
|
||||
int nss, i;
|
||||
SSCB *pSS;
|
||||
STATE *pState;
|
||||
int nss, i, nstates;
|
||||
struct seqSS *pSeqSS;
|
||||
struct seqState *pSeqState;
|
||||
|
||||
for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++)
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
pSS->task_id = 0;
|
||||
/* 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);
|
||||
#endif DEBUG
|
||||
/* Create a binary semaphore for synchronizing events in a SS */
|
||||
pSS->syncSemId = semBCreate(SEM_Q_FIFO, SEM_FULL);
|
||||
if (pSS->syncSemId == NULL)
|
||||
@@ -375,12 +324,100 @@ SPROG *pSP;
|
||||
|
||||
}
|
||||
|
||||
pSS->current_state = 0; /* initial state */
|
||||
pSS->next_state = 0;
|
||||
pSS->action_complete = TRUE;
|
||||
/* 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 = pSeqState->actionFunc;
|
||||
pState->eventFunc = pSeqState->eventFunc;
|
||||
pState->delayFunc = pSeqState->delayFunc;
|
||||
pState->pEventMask = pSeqState->pEventMask;
|
||||
#ifdef DEBUG
|
||||
logMsg("init_sscb: State Name=%s, Event Mask=0x%x\n",
|
||||
pState->pStateName, *pState->pEventMask);
|
||||
#endif DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
logMsg("init_sscb: numSS=%d\n", pSP->numSS);
|
||||
#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);
|
||||
#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)
|
||||
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);
|
||||
logMsg(" size=%d, dbOffset=%d\n", pDB->size, pDB->dbOffset);
|
||||
logMsg(" efId=%d, monFlag=%d, eventNum=%d\n",
|
||||
pDB->efId, pDB->monFlag, pDB->eventNum);
|
||||
#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);
|
||||
#endif
|
||||
|
||||
for (i = 0 ; i < MAX_MACROS; i++, pMac++)
|
||||
{
|
||||
pMac->pName = NULL;
|
||||
pMac->pValue = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Evaluate channel names by macro substitution.
|
||||
*/
|
||||
@@ -391,36 +428,77 @@ SPROG *pSP;
|
||||
CHAN *pDB;
|
||||
int i;
|
||||
|
||||
pDB = pSP->channels;
|
||||
for (i = 0; i < pSP->nchan; i++, pDB++)
|
||||
pDB = pSP->pChan;
|
||||
for (i = 0; i < pSP->numChans; i++, pDB++)
|
||||
{
|
||||
pDB->db_name = seqAlloc(pSP, MACRO_STR_LEN);
|
||||
seqMacEval(pDB->db_uname, pDB->db_name, MACRO_STR_LEN, pSP->mac_ptr);
|
||||
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);
|
||||
#endif DEBUG
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* seqAlloc: Allocate memory from the program scratch area.
|
||||
* Always round up to even no. bytes.
|
||||
/*
|
||||
* 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!
|
||||
*/
|
||||
char *seqAlloc(pSP, nChar)
|
||||
SPROG *pSP;
|
||||
int nChar;
|
||||
{
|
||||
char *pStr;
|
||||
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),
|
||||
|
||||
pStr = pSP->scr_ptr;
|
||||
/* round to even no. bytes */
|
||||
if ((nChar & 1) != 0)
|
||||
nChar++;
|
||||
if (pSP->scr_nleft >= nChar)
|
||||
"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),
|
||||
|
||||
"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++)
|
||||
{
|
||||
pSP->scr_ptr += nChar;
|
||||
pSP->scr_nleft -= nChar;
|
||||
return pStr;
|
||||
if (strcmp(pUserType, pMap->pTypeStr) == 0)
|
||||
{
|
||||
*pGetType = pMap->getType;
|
||||
*pPutType = pMap->putType;
|
||||
*pSize = pMap->size;
|
||||
*pOffset = pMap->offset;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
*pGetType = *pPutType = *pSize = *pOffset = 0; /* this shouldn't happen */
|
||||
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* seq_logInit() - Initialize logging.
|
||||
@@ -429,7 +507,7 @@ int nChar;
|
||||
LOCAL VOID seq_logInit(pSP)
|
||||
SPROG *pSP;
|
||||
{
|
||||
char *pname, *pvalue;
|
||||
char *pValue;
|
||||
int fd;
|
||||
|
||||
/* Create a logging resource locking semaphore */
|
||||
@@ -442,26 +520,25 @@ SPROG *pSP;
|
||||
pSP->logFd = ioGlobalStdGet(1); /* default fd is std out */
|
||||
|
||||
/* Check for logfile spec. */
|
||||
pname = "logfile";
|
||||
pvalue = seqMacValGet(pname, strlen(pname), pSP->mac_ptr);
|
||||
if (pvalue != NULL && strlen(pvalue) > 0)
|
||||
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);
|
||||
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);
|
||||
printf("logfile=%s, fd=%d\n", pValue, fd);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* seq_log
|
||||
* Log a message to the console or a file with time of day and task id.
|
||||
* The format looks like "mytask 12/13/91 10:07:43: <user's message>".
|
||||
* 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
|
||||
|
||||
VOID seq_log(pSP, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
||||
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 */
|
||||
@@ -481,7 +558,7 @@ int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
|
||||
|
||||
/* Convert to text format: "mm/dd/yy hh:mm:ss.nano-sec" */
|
||||
tsStampToText(&timeStamp, TS_TEXT_MMDDYY, pBfr);
|
||||
/* We're going to truncate the ".nano-sec" part */
|
||||
/* Truncate the ".nano-sec" part */
|
||||
if (pBfr[2] == '/') /* valid t-s? */
|
||||
pBfr += 17;
|
||||
|
||||
@@ -498,11 +575,13 @@ int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
|
||||
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\n", fd, errnoGet());
|
||||
printErrno(errnoGet());
|
||||
return;
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
/* If this is an NSF file flush the buffer */
|
||||
@@ -510,41 +589,19 @@ int arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
|
||||
{
|
||||
ioctl(fd, FIOSYNC, 0);
|
||||
}
|
||||
semGive(pSP->logSemId);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* seqLog() - State program interface to seq_log().
|
||||
* Does not require ptr to state program block.
|
||||
*/
|
||||
STATUS seqLog(fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
||||
char *fmt; /* format string */
|
||||
int arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8; /* arguments */
|
||||
{
|
||||
SPROG *pSP, *seqFindProg();
|
||||
|
||||
pSP = seqFindProg(taskIdSelf());
|
||||
if (pSP == NULL)
|
||||
return ERROR;
|
||||
|
||||
seq_log(pSP, fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
return OK;
|
||||
}
|
||||
/*
|
||||
* seq_optGet: return the value of an option.
|
||||
* FALSE means "-" and TRUE means "+".
|
||||
* seq_seqLog() - State program interface to seq_log().
|
||||
* Does not require ptr to state program block.
|
||||
*/
|
||||
BOOL seq_optGet(pSP, opt)
|
||||
SPROG *pSP;
|
||||
char *opt; /* one of the snc options as a strign (e.g. "a") */
|
||||
STATUS 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 */
|
||||
{
|
||||
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 'r': return ( (pSP->options & OPT_REENT) != 0);
|
||||
case 'e': return ( (pSP->options & OPT_NEWEF) != 0);
|
||||
default: return FALSE;
|
||||
}
|
||||
SPROG *pSP;
|
||||
|
||||
pSP = ((SSCB *)ssId)->sprog;
|
||||
return seq_log(pSP, fmt, arg1,arg2, arg3, arg4, arg5, arg6, arg7, arg8);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
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
|
||||
|
||||
|
||||
$Id$
|
||||
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.
|
||||
@@ -15,37 +16,38 @@
|
||||
29apr92,ajk Added mutual exclusion locks
|
||||
17Jul92,rcz Changed semBCreate call for V5 vxWorks, maybe should be semMCreate ???
|
||||
***************************************************************************/
|
||||
#define DEBUG
|
||||
/*#define DEBUG*/
|
||||
#define ANSI
|
||||
#include "seq.h"
|
||||
#include "lstLib.h"
|
||||
|
||||
LOCAL SEM_ID seqProgListSemId;
|
||||
LOCAL int seqProgListInited = FALSE;
|
||||
LOCAL ELLLIST seqProgList;
|
||||
LOCAL LIST seqProgList;
|
||||
LOCAL VOID seqProgListInit();
|
||||
|
||||
typedef struct prog_node
|
||||
{
|
||||
ELLNODE node;
|
||||
NODE node;
|
||||
SPROG *pSP;
|
||||
} PROG_NODE;
|
||||
|
||||
#define seqListFirst(pList) (PROG_NODE *)ellFirst((ELLLIST *)pList)
|
||||
#define seqListFirst(pList) (PROG_NODE *)lstFirst((LIST *)pList)
|
||||
|
||||
#define seqListNext(pNode) (PROG_NODE *)ellNext((ELLNODE *)pNode)
|
||||
#define seqListNext(pNode) (PROG_NODE *)lstNext((NODE *)pNode)
|
||||
|
||||
/*
|
||||
* seqFindProg() - find a program in the state program list from task id.
|
||||
*/
|
||||
SPROG *seqFindProg(task_id)
|
||||
int task_id;
|
||||
SPROG *seqFindProg(taskId)
|
||||
int taskId;
|
||||
{
|
||||
PROG_NODE *pNode;
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int n;
|
||||
|
||||
if (!seqProgListInited || task_id == 0)
|
||||
if (!seqProgListInited || taskId == 0)
|
||||
return NULL;
|
||||
|
||||
semTake(seqProgListSemId, WAIT_FOREVER);
|
||||
@@ -54,15 +56,15 @@ int task_id;
|
||||
pNode = seqListNext(pNode) )
|
||||
{
|
||||
pSP = pNode->pSP;
|
||||
if (pSP->task_id == task_id)
|
||||
if (pSP->taskId == taskId)
|
||||
{
|
||||
semGive(seqProgListSemId);
|
||||
return pSP;
|
||||
}
|
||||
pSS = pSP->sscb;
|
||||
for (n = 0; n < pSP->nss; n++, pSS++)
|
||||
pSS = pSP->pSS;
|
||||
for (n = 0; n < pSP->numSS; n++, pSS++)
|
||||
{
|
||||
if (pSS->task_id == task_id)
|
||||
if (pSS->taskId == taskId)
|
||||
{
|
||||
semGive(seqProgListSemId);
|
||||
return pSP;
|
||||
@@ -122,7 +124,7 @@ SPROG *pSP;
|
||||
{
|
||||
semGive(seqProgListSemId);
|
||||
#ifdef DEBUG
|
||||
printf("Task %d already in list\n", pSP->task_id);
|
||||
printf("Task %d already in list\n", pSP->taskId);
|
||||
#endif
|
||||
return ERROR; /* already in list */
|
||||
}
|
||||
@@ -137,10 +139,10 @@ SPROG *pSP;
|
||||
}
|
||||
|
||||
pNode->pSP = pSP;
|
||||
ellAdd((ELLLIST *)&seqProgList, (ELLNODE *)pNode);
|
||||
lstAdd((LIST *)&seqProgList, (NODE *)pNode);
|
||||
semGive(seqProgListSemId);
|
||||
#ifdef DEBUG
|
||||
printf("Added task %d to list.\n", pSP->task_id);
|
||||
printf("Added task %d to list.\n", pSP->taskId);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
@@ -164,11 +166,11 @@ SPROG *pSP;
|
||||
{
|
||||
if (pNode->pSP == pSP)
|
||||
{
|
||||
ellDelete((ELLLIST *)&seqProgList, (ELLNODE *)pNode);
|
||||
lstDelete((LIST *)&seqProgList, (NODE *)pNode);
|
||||
semGive(seqProgListSemId);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("Deleted task %d from list.\n", pSP->task_id);
|
||||
printf("Deleted task %d from list.\n", pSP->taskId);
|
||||
#endif
|
||||
return OK;
|
||||
}
|
||||
@@ -184,7 +186,7 @@ SPROG *pSP;
|
||||
LOCAL VOID seqProgListInit()
|
||||
{
|
||||
/* Init linked list */
|
||||
ellInit(&seqProgList);
|
||||
lstInit(&seqProgList);
|
||||
|
||||
/* Create a semaphore for mutual exclusion */
|
||||
seqProgListSemId = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
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
|
||||
|
||||
$Id$
|
||||
DESCRIPTION: Task querry & debug routines for run-time sequencer:
|
||||
seqShow - prints state set info.
|
||||
seqChanShow - printf channel (pv) info.
|
||||
@@ -21,17 +21,17 @@
|
||||
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 */
|
||||
/*#define DEBUG 1*/
|
||||
|
||||
#include "seq.h"
|
||||
|
||||
int seqShow(int);
|
||||
int seqChanShow(int);
|
||||
LOCAL VOID wait_rtn();
|
||||
LOCAL VOID printValue(void *, int, int, int);
|
||||
LOCAL VOID printType(int);
|
||||
int seqChanShow(int, char *);
|
||||
LOCAL int wait_rtn();
|
||||
LOCAL VOID printValue(char *, int, int);
|
||||
LOCAL SPROG *seqQryFind(int);
|
||||
LOCAL seqShowAll();
|
||||
|
||||
@@ -53,32 +53,27 @@ int tid;
|
||||
|
||||
/* 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->name);
|
||||
printf(" Memory layout:\n");
|
||||
printf("\tpSP=%d=0x%x\n", pSP, pSP);
|
||||
printf("\tdyn_ptr=%d=0x%x\n", pSP->dyn_ptr, pSP->dyn_ptr);
|
||||
printf("\tsscb=%d=0x%x\n", pSP->sscb, pSP->sscb);
|
||||
printf("\tstates=%d=0x%x\n", pSP->states, pSP->states);
|
||||
printf("\tuser_area=%d=0x%x\n", pSP->user_area, pSP->user_area);
|
||||
printf("\tuser_size=%d=0x%x\n", pSP->user_size, pSP->user_size);
|
||||
printf("\tmac_ptr=%d=0x%x\n", pSP->mac_ptr, pSP->mac_ptr);
|
||||
printf("\tscr_ptr=%d=0x%x\n", pSP->scr_ptr, pSP->scr_ptr);
|
||||
printf("\tscr_nleft=%d=0x%x\n\n", pSP->scr_nleft, pSP->scr_nleft);
|
||||
printf(" initial task id=%d=0x%x\n", pSP->task_id, pSP->task_id);
|
||||
printf(" task priority=%d\n", pSP->task_priority);
|
||||
printf(" number of state sets=%d\n", pSP->nss);
|
||||
printf(" number of channels=%d\n", pSP->nchan);
|
||||
printf(" number of channels connected=%d\n", pSP->conn_count);
|
||||
printf(" options: async=%d, debug=%d, reent=%d, conn=%d, newef=%d\n",
|
||||
printf("State Program: \"%s\"\n", pSP->pProgName);
|
||||
printf(" initial task id=%d=0x%x\n", pSP->taskId, pSP->taskId);
|
||||
printf(" task priority=%d\n", pSP->taskPriority);
|
||||
printf(" number of state sets=%d\n", pSP->numSS);
|
||||
printf(" number of channels=%d\n", pSP->numChans);
|
||||
printf(" number of channels assigned=%d\n", pSP->assignCount);
|
||||
printf(" number of channels connected=%d\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_REENT) != 0), ((pSP->options & OPT_CONN) != 0),
|
||||
((pSP->options & OPT_NEWEF) != 0) );
|
||||
((pSP->options & OPT_NEWEF) != 0), ((pSP->options & OPT_REENT) != 0),
|
||||
((pSP->options & OPT_CONN) != 0) );
|
||||
printf(" log file fd=%d\n", pSP->logFd);
|
||||
status = ioctl(pSP->logFd, FIOGETNAME, (int)file_name);
|
||||
if (status != ERROR)
|
||||
@@ -87,88 +82,129 @@ int tid;
|
||||
printf("\n");
|
||||
|
||||
/* Print state set info */
|
||||
for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++)
|
||||
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
|
||||
{
|
||||
wait_rtn();
|
||||
printf(" State Set: \"%s\"\n", pSS->pSSName);
|
||||
|
||||
printf(" State Set: \"%s\"\n", pSS->name);
|
||||
printf(" task name=%s; ", taskName(pSS->taskId));
|
||||
|
||||
printf(" task name=%s; ", taskName(pSS->task_id));
|
||||
printf(" task id=%d=0x%x\n", pSS->taskId, pSS->taskId);
|
||||
|
||||
printf(" id=%d=0x%x\n", pSS->task_id, pSS->task_id);
|
||||
pST = pSS->pStates;
|
||||
printf(" First state = \"%s\"\n", pST->pStateName);
|
||||
|
||||
pST = pSS->states;
|
||||
printf(" First state = \"%s\"\n", pSS->states->name);
|
||||
pST = pSS->pStates + pSS->currentState;
|
||||
printf(" Current state = \"%s\"\n", pST->pStateName);
|
||||
|
||||
pST = pSS->states + pSS->current_state;
|
||||
printf(" Current state = \"%s\"\n", pST->name);
|
||||
pST = pSS->pStates + pSS->prevState;
|
||||
printf(" Previous state = \"%s\"\n", pST->pStateName);
|
||||
|
||||
pST = pSS->states + pSS->prev_state;
|
||||
printf(" Previous state = \"%s\"\n", pST->name);
|
||||
|
||||
time = pSS->time/60.0;
|
||||
printf("\tTime state was entered = %.1f seconds)\n", time);
|
||||
time = (tickGet() - pSS->time)/60.0;
|
||||
time = (tickGet() - pSS->timeEntered)/60.0;
|
||||
printf("\tElapsed time since state was entered = %.1f seconds)\n",
|
||||
time);
|
||||
|
||||
printf("\tNumber delays queued=%d\n", pSS->ndelay);
|
||||
for (n = 0; n < pSS->ndelay; n++)
|
||||
#ifdef DEBUG
|
||||
printf(" Queued time delays:\n");
|
||||
for (n = 0; n < pSS->numDelays; n++)
|
||||
{
|
||||
time = pSS->timeout[n]/60.0;
|
||||
printf("\t\ttimeout[%d] = %.1f seconds\n", n, time);
|
||||
printf("\tdelay[%2d]=%d", n, pSS->delay[n]);
|
||||
if (pSS->delayExpired[n])
|
||||
printf(" - expired");
|
||||
printf("\n");
|
||||
}
|
||||
#endif DEBUG
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* seqChanQry() - Querry the sequencer for channel information.
|
||||
* seqChanShow() - Show channel information for a state program.
|
||||
*/
|
||||
int seqChanShow(tid)
|
||||
int tid;
|
||||
int seqChanShow(tid, pStr)
|
||||
int tid; /* task id or name */
|
||||
char *pStr; /* optional pattern matching string */
|
||||
{
|
||||
SPROG *pSP;
|
||||
CHAN *pDB;
|
||||
int nch;
|
||||
int nch, n;
|
||||
float time;
|
||||
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;
|
||||
|
||||
pDB = pSP->channels;
|
||||
printf("State Program: \"%s\"\n", pSP->name);
|
||||
printf("Number of channels=%d\n", pSP->nchan);
|
||||
printf("State Program: \"%s\"\n", pSP->pProgName);
|
||||
printf("Number of channels=%d\n", pSP->numChans);
|
||||
|
||||
for (nch = 0; nch < pSP->nchan; nch++, pDB++)
|
||||
if (pStr != NULL)
|
||||
{
|
||||
printf("\nChannel name: \"%s\"\n", pDB->db_name);
|
||||
printf(" Unexpanded name: \"%s\"\n", pDB->db_uname);
|
||||
printf(" Variable=%d=0x%x\n", pDB->var, pDB->var);
|
||||
printf(" Size=%d bytes\n", pDB->size);
|
||||
printf(" Count=%d\n", pDB->count);
|
||||
printType(pDB->put_type);
|
||||
printValue((void *)pDB->var, pDB->size, pDB->count,
|
||||
pDB->put_type);
|
||||
printf(" DB get request type=%d\n", pDB->get_type);
|
||||
printf(" DB put request type=%d\n", pDB->put_type);
|
||||
printf(" monitor flag=%d\n", pDB->mon_flag);
|
||||
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 %d:\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 = %d = 0x%x\n", pDB->pVar, pDB->pVar);
|
||||
printf(" type = %s\n", pDB->pVarType);
|
||||
printf(" count = %d\n", pDB->count);
|
||||
printValue(pDB->pVar, pDB->putType, pDB->count);
|
||||
printf(" Monitor flag=%d\n", pDB->monFlag);
|
||||
|
||||
if (pDB->monitored)
|
||||
printf(" Monitored\n");
|
||||
printf(" Monitored\n");
|
||||
else
|
||||
printf(" Not monitored\n");
|
||||
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->get_complete)
|
||||
if(pDB->getComplete)
|
||||
printf(" Last get completed\n");
|
||||
else
|
||||
printf(" Get not completed or no get issued\n");
|
||||
@@ -176,118 +212,117 @@ int tid;
|
||||
printf(" Status=%d\n", pDB->status);
|
||||
printf(" Severity=%d\n", pDB->severity);
|
||||
|
||||
printf(" Delta=%g\n", pDB->delta);
|
||||
printf(" Timeout=%g\n", pDB->timeout);
|
||||
wait_rtn();
|
||||
/* 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 VOID wait_rtn()
|
||||
LOCAL int wait_rtn()
|
||||
{
|
||||
char bfr;
|
||||
printf("Hit RETURN to continue\n");
|
||||
do {
|
||||
read(STD_IN, &bfr, 1);
|
||||
} while (bfr != '\n');
|
||||
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;
|
||||
}
|
||||
|
||||
/* Special union to simplify printing values */
|
||||
struct dbr_union {
|
||||
union {
|
||||
char c;
|
||||
short s;
|
||||
long l;
|
||||
float f;
|
||||
double d;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* Print the current internal value of a database channel */
|
||||
LOCAL VOID printValue(pvar, size, count, type)
|
||||
void *pvar;
|
||||
int size, count, type;
|
||||
LOCAL VOID printValue(pVal, type, count)
|
||||
char *pVal;
|
||||
int count, type;
|
||||
{
|
||||
struct dbr_union *pv = pvar;
|
||||
int i;
|
||||
char *c;
|
||||
short *s;
|
||||
long *l;
|
||||
float *f;
|
||||
double *d;
|
||||
|
||||
if (count > 5)
|
||||
count = 5;
|
||||
|
||||
printf(" Value =");
|
||||
while (count-- > 0)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DBR_STRING:
|
||||
printf(" %s", pv->u.c);
|
||||
break;
|
||||
|
||||
case DBR_CHAR:
|
||||
printf(" %d", pv->u.c);
|
||||
break;
|
||||
|
||||
case DBR_SHORT:
|
||||
printf(" %d", pv->u.s);
|
||||
break;
|
||||
|
||||
case DBR_LONG:
|
||||
printf(" %d", pv->u.l);
|
||||
break;
|
||||
|
||||
case DBR_FLOAT:
|
||||
printf(" %g", pv->u.f);
|
||||
break;
|
||||
|
||||
case DBR_DOUBLE:
|
||||
printf(" %lg", pv->u.d);
|
||||
break;
|
||||
}
|
||||
|
||||
pv = (struct dbr_union *)((char *)pv + size);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Print the data type of a channel */
|
||||
LOCAL VOID printType(type)
|
||||
int type;
|
||||
{
|
||||
char *type_str;
|
||||
|
||||
switch (type)
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DBR_STRING:
|
||||
type_str = "string";
|
||||
c = (char *)pVal;
|
||||
for (i = 0; i < count; i++, c += MAX_STRING_SIZE)
|
||||
{
|
||||
printf(" %s", c);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBR_CHAR:
|
||||
type_str = "char";
|
||||
case DBR_CHAR:
|
||||
c = (char *)pVal;
|
||||
for (i = 0; i < count; i++, c++)
|
||||
{
|
||||
printf(" %d", *c);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBR_SHORT:
|
||||
type_str = "short";
|
||||
s = (short *)pVal;
|
||||
for (i = 0; i < count; i++, s++)
|
||||
{
|
||||
printf(" %d", *s);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBR_LONG:
|
||||
type_str = "long";
|
||||
l = (long *)pVal;
|
||||
for (i = 0; i < count; i++, l++)
|
||||
{
|
||||
printf(" %d", *l);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBR_FLOAT:
|
||||
type_str = "float";
|
||||
f = (float *)pVal;
|
||||
for (i = 0; i < count; i++, f++)
|
||||
{
|
||||
printf(" %g", *f);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBR_DOUBLE:
|
||||
type_str = "double";
|
||||
break;
|
||||
|
||||
default:
|
||||
type_str = "?";
|
||||
d = (double *)pVal;
|
||||
for (i = 0; i < count; i++, d++)
|
||||
{
|
||||
printf(" %g", *d);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf(" Type = %s\n", type_str);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Find a state program associated with a given task id */
|
||||
@@ -311,13 +346,6 @@ int tid;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for correct magic number */
|
||||
if (pSP->magic != MAGIC)
|
||||
{
|
||||
printf("Sorry, wrong magic number\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pSP;
|
||||
}
|
||||
|
||||
@@ -334,15 +362,15 @@ SPROG *pSP;
|
||||
if (seqProgCount++ == 0)
|
||||
printf("Program Name Task ID Task Name SS Name\n\n");
|
||||
|
||||
progName = pSP->name;
|
||||
for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++)
|
||||
progName = pSP->pProgName;
|
||||
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
|
||||
{
|
||||
if (pSS->task_id == 0)
|
||||
if (pSS->taskId == 0)
|
||||
ptaskName = "(no task)";
|
||||
else
|
||||
ptaskName = taskName(pSS->task_id);
|
||||
ptaskName = taskName(pSS->taskId);
|
||||
printf("%-16s %-10d %-16s %-16s\n",
|
||||
progName, pSS->task_id, ptaskName, pSS->name );
|
||||
progName, pSS->taskId, ptaskName, pSS->pSSName );
|
||||
progName = "";
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/**************************************************************************
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, 1991, 1992
|
||||
The Regents of the University of California
|
||||
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
|
||||
|
||||
$Id$
|
||||
DESCRIPTION: Seq_tasks.c: Task creation and control for sequencer
|
||||
state sets.
|
||||
|
||||
@@ -20,14 +21,21 @@
|
||||
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().
|
||||
9aug93,ajk Added calls to taskwdInsert() & taskwdRemove().
|
||||
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
|
||||
***************************************************************************/
|
||||
/*#define DEBUG*/
|
||||
#define ANSI
|
||||
#include "seqCom.h"
|
||||
#include "seq.h"
|
||||
#include <taskwd.h>
|
||||
|
||||
/* Function declarations */
|
||||
LOCAL VOID ss_task_init(SPROG *, SSCB *);
|
||||
LOCAL VOID seq_clearDelay(SSCB *);
|
||||
LOCAL long seq_getTimeout(SSCB *);
|
||||
|
||||
#define TASK_NAME_SIZE 10
|
||||
@@ -37,10 +45,10 @@ LOCAL long seq_getTimeout(SSCB *);
|
||||
/*
|
||||
* sequencer() - Sequencer main task entry point.
|
||||
* */
|
||||
sequencer(pSP, stack_size, ptask_name)
|
||||
sequencer(pSP, stack_size, pTaskName)
|
||||
SPROG *pSP; /* ptr to original (global) state program table */
|
||||
int stack_size; /* stack size */
|
||||
char *ptask_name; /* Parent task name */
|
||||
char *pTaskName; /* Parent task name */
|
||||
{
|
||||
SSCB *pSS;
|
||||
STATE *pST;
|
||||
@@ -49,9 +57,9 @@ char *ptask_name; /* Parent task name */
|
||||
extern VOID ss_entry();
|
||||
extern int seqAuxTaskId;
|
||||
|
||||
pSP->task_id = taskIdSelf(); /* my task id */
|
||||
pSS = pSP->sscb;
|
||||
pSS->task_id = pSP->task_id;
|
||||
pSP->taskId = taskIdSelf(); /* my task id */
|
||||
pSS = pSP->pSS;
|
||||
pSS->taskId = pSP->taskId;
|
||||
|
||||
/* Add the program to the state program list */
|
||||
seqAddProg(pSP);
|
||||
@@ -63,19 +71,19 @@ char *ptask_name; /* Parent task name */
|
||||
seq_connect(pSP);
|
||||
|
||||
/* Additional state set task names are derived from the first ss */
|
||||
if (strlen(ptask_name) > TASK_NAME_SIZE)
|
||||
ptask_name[TASK_NAME_SIZE] = 0;
|
||||
if (strlen(pTaskName) > TASK_NAME_SIZE)
|
||||
pTaskName[TASK_NAME_SIZE] = 0;
|
||||
|
||||
/* Create each additional state set task */
|
||||
for (nss = 1, pSS = pSP->sscb + 1; nss < pSP->nss; nss++, pSS++)
|
||||
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", ptask_name, nss);
|
||||
sprintf(task_name, "%s_%d", pTaskName, nss);
|
||||
|
||||
/* Spawn the task */
|
||||
task_id = taskSpawn(
|
||||
task_name, /* task name */
|
||||
SPAWN_PRIORITY+pSS->task_priority, /* priority */
|
||||
SPAWN_PRIORITY+pSS->taskPriority, /* priority */
|
||||
SPAWN_OPTIONS, /* task options */
|
||||
stack_size, /* stack size */
|
||||
(FUNCPTR)ss_entry, /* entry point */
|
||||
@@ -85,7 +93,7 @@ char *ptask_name; /* Parent task name */
|
||||
}
|
||||
|
||||
/* First state set jumps directly to entry point */
|
||||
ss_entry(pSP, pSP->sscb);
|
||||
ss_entry(pSP, pSP->pSS);
|
||||
}
|
||||
/*
|
||||
* ss_entry() - Task entry point for all state sets.
|
||||
@@ -100,6 +108,8 @@ SSCB *pSS;
|
||||
long delay;
|
||||
char *pVar;
|
||||
LOCAL VOID seq_waitConnect();
|
||||
int nWords;
|
||||
SS_ID ssId;
|
||||
|
||||
/* Initialize all ss tasks */
|
||||
ss_task_init(pSP, pSS);
|
||||
@@ -109,29 +119,29 @@ SSCB *pSS;
|
||||
seq_waitConnect(pSP, pSS);
|
||||
|
||||
/* Initilaize state set to enter the first state */
|
||||
pST = pSS->states;
|
||||
pSS->current_state = 0;
|
||||
pST = pSS->pStates;
|
||||
pSS->currentState = 0;
|
||||
|
||||
/* Use the event mask for this state */
|
||||
pSS->pMask = (pST->eventMask);
|
||||
pSS->pMask = (pST->pEventMask);
|
||||
nWords = (pSP->numEvents + NBITS - 1) / NBITS;
|
||||
|
||||
/* Local ptr to user variables (for reentrant code only) */
|
||||
pVar = pSP->user_area;
|
||||
pVar = pSP->pVar;
|
||||
|
||||
/* State set id */
|
||||
ssId = (SS_ID)pSS;
|
||||
|
||||
/*
|
||||
* ============= Main loop ==============
|
||||
*/
|
||||
while (1)
|
||||
{
|
||||
pSS->time = tickGet(); /* record time we entered this state */
|
||||
seq_clearDelay(pSS); /* Clear delay list */
|
||||
pST->delayFunc(ssId, pVar); /* Set up new delay list */
|
||||
|
||||
/* Call delay function to set up delays */
|
||||
pSS->ndelay = 0;
|
||||
pST->delay_func(pSP, pSS, pVar);
|
||||
|
||||
/* Generate a phoney event.
|
||||
* This guarantees that a when() is always executed at
|
||||
* least once when a state is entered. */
|
||||
/* Setting this semaphor here guarantees that a when() is always
|
||||
* executed at least once when a state is first entered. */
|
||||
semGive(pSS->syncSemId);
|
||||
|
||||
/*
|
||||
@@ -139,7 +149,7 @@ SSCB *pSS;
|
||||
*/
|
||||
do {
|
||||
/* Wake up on CA event, event flag, or expired time delay */
|
||||
delay = seq_getTimeout(pSS);
|
||||
delay = seq_getTimeout(pSS); /* min. delay from list */
|
||||
if (delay > 0)
|
||||
semTake(pSS->syncSemId, delay);
|
||||
|
||||
@@ -149,38 +159,43 @@ SSCB *pSS;
|
||||
*/
|
||||
semTake(pSP->caSemId, WAIT_FOREVER);
|
||||
|
||||
ev_trig = pST->event_func(pSP, pSS, pVar); /* check events */
|
||||
ev_trig = pST->eventFunc(ssId, pVar,
|
||||
&pSS->transNum, &pSS->nextState); /* check events */
|
||||
|
||||
if ( ev_trig && (pSP->options & OPT_NEWEF) == 0 )
|
||||
/* 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 < NWRDS; i++)
|
||||
pSP->events[i] = pSP->events[i] & !pSS->pMask[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->states + pSS->next_state;
|
||||
pSS->pMask = (pStNext->eventMask);
|
||||
pStNext = pSS->pStates + pSS->nextState;
|
||||
pSS->pMask = (pStNext->pEventMask);
|
||||
|
||||
/* Execute the action for this event */
|
||||
pSS->action_complete = FALSE;
|
||||
pST->action_func(pSP, pSS, pVar);
|
||||
pST->actionFunc(ssId, pVar, pSS->transNum);
|
||||
|
||||
/* Flush any outstanding DB requests */
|
||||
ca_flush_io();
|
||||
|
||||
/* Change to next state */
|
||||
pSS->prev_state = pSS->current_state;
|
||||
pSS->current_state = pSS->next_state;
|
||||
pST = pSS->states + pSS->current_state;
|
||||
pSS->action_complete = TRUE;
|
||||
pSS->prevState = pSS->currentState;
|
||||
pSS->currentState = pSS->nextState;
|
||||
pST = pSS->pStates + pSS->currentState;
|
||||
}
|
||||
}
|
||||
/* Initialize state-set tasks */
|
||||
@@ -191,14 +206,14 @@ SSCB *pSS;
|
||||
extern int seqAuxTaskId;
|
||||
|
||||
/* Get this task's id */
|
||||
pSS->task_id = taskIdSelf();
|
||||
pSS->taskId = taskIdSelf();
|
||||
|
||||
/* Import Channel Access context from the auxillary seq. task */
|
||||
if (pSP->task_id != pSS->task_id)
|
||||
if (pSP->taskId != pSS->taskId)
|
||||
ca_import(seqAuxTaskId);
|
||||
|
||||
/* Register this task with the EPICS watchdog (no callback function) */
|
||||
taskwdInsert(pSS->task_id, (VOIDFUNCPTR)0, (VOID *)0);
|
||||
taskwdInsert(pSS->taskId, (VOIDFUNCPTR)0, (VOID *)0);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -212,94 +227,82 @@ SSCB *pSS;
|
||||
long delay;
|
||||
|
||||
delay = 600; /* 10, 20, 30, 40, 40,... sec */
|
||||
while (pSP->conn_count < pSP->nchan)
|
||||
while (pSP->connCount < pSP->assignCount)
|
||||
{
|
||||
status = semTake(pSS->syncSemId, delay);
|
||||
if ((status != OK) && (pSP-> task_id == pSS->task_id))
|
||||
if ((status != OK) && (pSP-> taskId == pSS->taskId))
|
||||
{
|
||||
logMsg("%d of %d channels connected\n",
|
||||
pSP->conn_count, pSP->nchan);
|
||||
logMsg("%d of %d assigned channels have connected\n",
|
||||
pSP->connCount, pSP->assignCount);
|
||||
}
|
||||
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 MAX_DELAY if no delays pending */
|
||||
LOCAL long seq_getTimeout(pSS)
|
||||
SSCB *pSS;
|
||||
SSCB *pSS;
|
||||
{
|
||||
int ndelay;
|
||||
long timeout; /* expiration clock time (tics) */
|
||||
long delay, delayMin; /* remaining & min. delay (tics) */
|
||||
long delay, delayMin, delayN;
|
||||
|
||||
if (pSS->ndelay == 0)
|
||||
if (pSS->numDelays == 0)
|
||||
return MAX_DELAY;
|
||||
|
||||
delay = tickGet() - pSS->timeEntered; /* actual delay since state entered */
|
||||
|
||||
delayMin = MAX_DELAY; /* start with largest possible delay */
|
||||
|
||||
/* Find the minimum delay among all non-expired timeouts */
|
||||
for (ndelay = 0; ndelay < pSS->ndelay; ndelay++)
|
||||
for (ndelay = 0; ndelay < pSS->numDelays; ndelay++)
|
||||
{
|
||||
timeout = pSS->timeout[ndelay];
|
||||
if (timeout == 0)
|
||||
continue; /* already expired */
|
||||
delay = timeout - tickGet(); /* convert timeout to remaining delay */
|
||||
if (delay <= 0)
|
||||
if (pSS->delayExpired[ndelay])
|
||||
continue; /* skip if this delay entry already expired */
|
||||
|
||||
delayN = pSS->delay[ndelay];
|
||||
if (delay >= delayN)
|
||||
{ /* just expired */
|
||||
delayMin = 0;
|
||||
pSS->timeout[ndelay] = 0; /* mark as expired */
|
||||
pSS->delayExpired[ndelay] = TRUE; /* mark as expired */
|
||||
return 0;
|
||||
}
|
||||
else if (delay < delayMin)
|
||||
else if (delayN < delayMin)
|
||||
{
|
||||
delayMin = delay; /* this is the min. delay so far */
|
||||
delayMin = delayN; /* this is the min. delay so far */
|
||||
}
|
||||
}
|
||||
delay = delayMin - delay;
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
|
||||
return delayMin;
|
||||
}
|
||||
/* Set-up for delay() on entering a state. This routine is called
|
||||
by the state program for each delay in the "when" statement */
|
||||
VOID seq_start_delay(pSP, pSS, delay_id, delay)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int delay_id; /* delay id */
|
||||
float delay;
|
||||
{
|
||||
int td_tics;
|
||||
|
||||
/* Note: the following 2 lines could be combined, but doing so produces
|
||||
* the undefined symbol "Mund", which is not in VxWorks library */
|
||||
td_tics = delay*60.0;
|
||||
pSS->timeout[delay_id] = pSS->time + td_tics;
|
||||
delay_id += 1;
|
||||
if (delay_id > pSS->ndelay)
|
||||
pSS->ndelay = delay_id;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test for time-out expired */
|
||||
BOOL seq_test_delay(pSP, pSS, delay_id)
|
||||
SPROG *pSP;
|
||||
SSCB *pSS;
|
||||
int delay_id;
|
||||
{
|
||||
if (pSS->timeout[delay_id] == 0)
|
||||
return TRUE; /* previously expired t-o */
|
||||
|
||||
if (tickGet() >= pSS->timeout[delay_id])
|
||||
{
|
||||
pSS->timeout[delay_id] = 0; /* mark as expired */
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
return delay;
|
||||
}
|
||||
/*
|
||||
* Delete all state set tasks and do general clean-up.
|
||||
* General procedure is:
|
||||
* 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.
|
||||
@@ -310,27 +313,46 @@ int delay_id;
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
sprog_delete(tid)
|
||||
int tid;
|
||||
int tid; /* task being deleted */
|
||||
{
|
||||
int nss, tid_ss;
|
||||
SPROG *pSP, *seqFindProg();
|
||||
SSCB *pSS;
|
||||
|
||||
SPROG *pSP;
|
||||
extern int seq_cleanup();
|
||||
SEM_ID cleanupSem;
|
||||
|
||||
pSP = seqFindProg(tid);
|
||||
if (pSP == NULL)
|
||||
return -1; /* not a state program task */
|
||||
|
||||
logMsg("Delete %s: pSP=%d=0x%x, tid=%d\n",
|
||||
pSP->name, pSP, pSP, tid);
|
||||
/* Create a semaphore for cleanup task */
|
||||
cleanupSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
|
||||
|
||||
/* Is this a real sequencer task? */
|
||||
if (pSP->magic != MAGIC)
|
||||
{
|
||||
logMsg(" Not main state program task\n");
|
||||
return -1;
|
||||
}
|
||||
/* Spawn the cleanup task */
|
||||
taskSpawn("seqCleanup", SPAWN_PRIORITY-1, VX_FP_TASK, 2000, seq_cleanup,
|
||||
tid, (int)pSP, (int)cleanupSem, 0,0,0,0,0,0,0);
|
||||
|
||||
/* Wait for cleanup task completion */
|
||||
semTake(cleanupSem, WAIT_FOREVER);
|
||||
semDelete(cleanupSem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cleanup task */
|
||||
seq_cleanup(tid, pSP, cleanupSem)
|
||||
int tid;
|
||||
SPROG *pSP;
|
||||
SEM_ID cleanupSem; /* indicate cleanup is finished */
|
||||
{
|
||||
int nss, tid_ss;
|
||||
SSCB *pSS;
|
||||
|
||||
logMsg("Delete %s: pSP=%d=0x%x, tid=%d\n",
|
||||
pSP->pProgName, pSP, pSP, tid);
|
||||
|
||||
/* Wait for log semaphore (in case a task is doing a write) */
|
||||
semTake(pSP->logSemId, 600);
|
||||
@@ -338,20 +360,20 @@ int tid;
|
||||
/* Remove tasks' watchdog & suspend all state set tasks except self */
|
||||
#ifdef DEBUG
|
||||
logMsg(" Suspending state set tasks:\n");
|
||||
#endif /*DEBUG */
|
||||
pSS = pSP->sscb;
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
#endif DEBUG
|
||||
pSS = pSP->pSS;
|
||||
for (nss = 0; nss < pSP->numSS; nss++, pSS++)
|
||||
{
|
||||
tid_ss = pSS->task_id;
|
||||
tid_ss = pSS->taskId;
|
||||
|
||||
/* Remove the task from EPICS watchdog */
|
||||
taskwdRemove(tid_ss);
|
||||
|
||||
if ( (tid_ss != 0) && (tid != tid_ss) )
|
||||
if (tid_ss != taskIdSelf() )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logMsg(" suspend task: tid=%d\n", tid_ss);
|
||||
#endif /*DEBUG */
|
||||
#endif DEBUG
|
||||
taskSuspend(tid_ss);
|
||||
}
|
||||
}
|
||||
@@ -360,21 +382,21 @@ int tid;
|
||||
semGive(pSP->logSemId);
|
||||
|
||||
/* Call user exit routine (only if task has run) */
|
||||
if (pSP->sscb->task_id != 0)
|
||||
if (pSP->pSS->taskId != 0)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logMsg(" Call exit function\n");
|
||||
#endif /*DEBUG */
|
||||
pSP->exit_func(pSP, pSP->user_area);
|
||||
#endif DEBUG
|
||||
pSP->exitFunc( (SS_ID)pSP->pSS, pSP->pVar);
|
||||
}
|
||||
|
||||
/* Disconnect all channels */
|
||||
seq_disconnect(pSP);
|
||||
|
||||
/* Cancel the CA context for each state set task */
|
||||
for (nss = 0, pSS = pSP->sscb; nss < pSP->nss; nss++, pSS++)
|
||||
for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
|
||||
{
|
||||
ca_import_cancel(pSS->task_id);
|
||||
ca_import_cancel(pSS->taskId);
|
||||
}
|
||||
|
||||
/* Close the log file */
|
||||
@@ -382,7 +404,7 @@ int tid;
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logMsg("Closing log fd=%d\n", pSP->logFd);
|
||||
#endif /*DEBUG */
|
||||
#endif DEBUG
|
||||
close(pSP->logFd);
|
||||
pSP->logFd = ioGlobalStdGet(1);
|
||||
}
|
||||
@@ -391,15 +413,15 @@ int tid;
|
||||
seqDelProg(pSP);
|
||||
|
||||
/* Delete state set tasks (except self) & delete their semaphores */
|
||||
pSS = pSP->sscb;
|
||||
for (nss = 0; nss < pSP->nss; nss++, pSS++)
|
||||
pSS = pSP->pSS;
|
||||
for (nss = 0; nss < pSP->numSS; nss++, pSS++)
|
||||
{
|
||||
tid_ss = pSS->task_id;
|
||||
tid_ss = pSS->taskId;
|
||||
if ( (tid != tid_ss) && (tid_ss != 0) )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logMsg(" delete ss task: tid=%d\n", tid_ss);
|
||||
#endif /*DEBUG */
|
||||
#endif DEBUG
|
||||
taskDelete(tid_ss);
|
||||
}
|
||||
|
||||
@@ -414,15 +436,58 @@ int tid;
|
||||
semDelete(pSP->caSemId);
|
||||
semDelete(pSP->logSemId);
|
||||
|
||||
/* Free the memory that was allocated for the task area */
|
||||
#ifdef DEBUG
|
||||
logMsg("free pSP->dyn_ptr=0x%x\n", pSP->dyn_ptr);
|
||||
#endif /*DEBUG */
|
||||
/* Free all allocated memory */
|
||||
taskDelay(5);
|
||||
free(pSP->dyn_ptr);
|
||||
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().
|
||||
|
||||
@@ -3,11 +3,15 @@
|
||||
GTA PROJECT AT division
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
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.
|
||||
***************************************************************************/
|
||||
/* SNC - State Notation Compiler.
|
||||
* The general structure of a state program is:
|
||||
@@ -31,13 +35,12 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "parse.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif /* TRUE */
|
||||
#endif TRUE
|
||||
|
||||
extern int line_num; /* input file line no. */
|
||||
%}
|
||||
@@ -74,10 +77,11 @@ extern int line_num; /* input file line no. */
|
||||
%type <ival> type
|
||||
%type <pchar> subscript binop asgnop unop
|
||||
%type <pexpr> state_set_list state_set state_list state transition_list transition
|
||||
%type <pexpr> parameter expr
|
||||
%type <pexpr> expr compound_expr assign_list bracked_expr
|
||||
%type <pexpr> statement stmt_list compound_stmt if_stmt else_stmt while_stmt
|
||||
%type <pexpr> for_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
|
||||
@@ -112,33 +116,60 @@ defn_stmt /* individual definitions for SNL (preceeds state sets) */
|
||||
| debug_stmt
|
||||
| sync_stmt
|
||||
| option_stmt
|
||||
| C_STMT { defn_c_stmt($1); }
|
||||
| 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_stmt($2, $4); }
|
||||
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, "0"); }
|
||||
| MONITOR NAME COMMA NUMBER SEMI_COLON { monitor_stmt($2, $4); }
|
||||
: MONITOR NAME SEMI_COLON { monitor_stmt($2, NULL); }
|
||||
| MONITOR NAME subscript SEMI_COLON { monitor_stmt($2, $3); }
|
||||
;
|
||||
|
||||
subscript /* e.g. [10] */
|
||||
: /* empty */ { $$ = 0; }
|
||||
| L_SQ_BRACKET NUMBER R_SQ_BRACKET { $$ = $2; }
|
||||
: L_SQ_BRACKET NUMBER R_SQ_BRACKET { $$ = $2; }
|
||||
;
|
||||
|
||||
debug_stmt
|
||||
: DEBUG_PRINT NUMBER SEMI_COLON { set_debug_print($2); }
|
||||
;
|
||||
|
||||
decl_stmt /* variable declarations (e.g. float x[20];) */
|
||||
: type NAME subscript SEMI_COLON { decl_stmt($1, $2, $3, (char *)0); }
|
||||
| type NAME subscript EQUAL NUMBER SEMI_COLON { decl_stmt($1, $2, $3, $5); }
|
||||
| type NAME subscript EQUAL STRING SEMI_COLON { decl_stmt($1, $2, $3, $5); }
|
||||
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 */
|
||||
@@ -153,8 +184,14 @@ type /* types for variables defined in SNL */
|
||||
;
|
||||
|
||||
sync_stmt /* sync <variable> <event flag> */
|
||||
: SYNC NAME TO NAME SEMI_COLON { sync_stmt($2, $4); }
|
||||
| SYNC NAME NAME SEMI_COLON { sync_stmt($2, $3); /* archaic syntax */ }
|
||||
: 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; */
|
||||
@@ -201,7 +238,8 @@ transition /* define a transition ("when" statment ) */
|
||||
|
||||
expr /* general expr: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */
|
||||
/* Expr *expression(int type, char *value, Expr *left, Expr *right) */
|
||||
: expr binop expr { $$ = expression(E_BINOP, $2, $1, $3); }
|
||||
: compound_expr { $$ = $1; }
|
||||
| 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); }
|
||||
@@ -211,12 +249,20 @@ expr /* general expr: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */
|
||||
| NUMBER { $$ = expression(E_CONST, $1, 0, 0); }
|
||||
| STRING { $$ = expression(E_STRING, $1, 0, 0); }
|
||||
| NAME { $$ = expression(E_VAR, $1, 0, 0); }
|
||||
| NAME L_PAREN parameter R_PAREN { $$ = expression(E_FUNC, $1, $3, 0); }
|
||||
| EXIT L_PAREN parameter R_PAREN { $$ = expression(E_FUNC, "exit", $3, 0); }
|
||||
| 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 L_SQ_BRACKET expr R_SQ_BRACKET %prec SUBSCRIPT
|
||||
{ $$ = expression(E_SUBSCR, "", $1, $3); }
|
||||
| /* empty */ { $$ = expression(E_EMPTY, "", 0, 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 */
|
||||
@@ -246,7 +292,6 @@ binop /* Binary operators */
|
||||
| BIT_AND { $$ = "&"; }
|
||||
| COMPLEMENT { $$ = "^"; }
|
||||
| MODULO { $$ = "%"; }
|
||||
| COMMA { $$ = ","; }
|
||||
| PERIOD { $$ = "."; } /* fudges structure elements */
|
||||
| POINTER { $$ = "->"; } /* fudges ptr to structure elements */
|
||||
;
|
||||
@@ -265,12 +310,6 @@ asgnop /* Assignment operators */
|
||||
| CMPL_EQUAL { $$ = "^="; }
|
||||
;
|
||||
|
||||
parameter /* expr, expr, .... */
|
||||
: expr { $$ = $1; }
|
||||
| parameter COMMA expr { $$ = link_expr($1, $3); }
|
||||
| /* empty */ { $$ = 0; }
|
||||
;
|
||||
|
||||
compound_stmt /* compound statement e.g. { ...; ...; ...; } */
|
||||
: L_BRACKET stmt_list R_BRACKET { $$ = expression(E_CMPND, "",$2, 0); }
|
||||
| error { snc_err("action statements"); }
|
||||
@@ -319,8 +358,21 @@ pp_code /* pre-processor code (e.g. # 1 "test.st") */
|
||||
;
|
||||
|
||||
global_c
|
||||
: C_STMT { global_c_stmt($1); }
|
||||
: 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"
|
||||
#include "snc_main.c"
|
||||
#include "snc_lex.c"
|
||||
|
||||
static int yyparse (void);
|
||||
|
||||
/* yyparse() is static, so we create global access to it */
|
||||
void Global_yyparse (void)
|
||||
{
|
||||
yyparse ();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
snc_lex.l,v 1.2 1995/06/27 15:26:09 wright Exp
|
||||
ENVIRONMENT: UNIX
|
||||
HISTORY:
|
||||
20nov91,ajk Added OPTION token.
|
||||
@@ -12,6 +12,14 @@
|
||||
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.
|
||||
***************************************************************************/
|
||||
/* Lexical analyzer for State Notation Compiler (snc).
|
||||
*
|
||||
@@ -22,10 +30,8 @@
|
||||
* Comments are recognized as part of the syntax.
|
||||
*/
|
||||
|
||||
/*
|
||||
#include "parse.h"
|
||||
#include "snc.h"
|
||||
*/
|
||||
#include "string.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
@@ -36,16 +42,14 @@
|
||||
#else
|
||||
#define RETURN(param) return(param);
|
||||
#endif
|
||||
#define STR_BFR_SIZE 300000
|
||||
#define STR_BFR_SIZE 1000
|
||||
|
||||
extern int line_num, c_line_num; /* input line number */
|
||||
extern int warn_opt; /* compiler warning flag */
|
||||
char str_bfr[STR_BFR_SIZE]; /* holding place for strings */
|
||||
char *str_next = str_bfr; /* current ptr to str_bfr */
|
||||
char *c_str; /* Start of current string in str_bfr */
|
||||
int nc;
|
||||
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;
|
||||
int one_line_c_code; /* TRUE for %%; FALSE for %{...}% */
|
||||
|
||||
%}
|
||||
|
||||
@@ -53,24 +57,25 @@ int one_line_c_code;
|
||||
%Start SNL C_CODE COMMENT STR PP PP_STR
|
||||
|
||||
NAME [a-zA-Z][a-zA-Z0-9_]*
|
||||
FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
FPNUM (([0-9]+)(\.[0-9]*)?)|(\.[0-9]+)
|
||||
OCTAL 0[0-7]+
|
||||
HEX 0x([0-9a-fA-F])+
|
||||
|
||||
%% /* Begin rules */
|
||||
<C_CODE>. *str_next++ = yytext[0];
|
||||
<C_CODE>. *pStr++ = yytext[0];
|
||||
<C_CODE>\n {
|
||||
*str_next++ = '\n';
|
||||
*pStr++ = 0;
|
||||
line_num++;
|
||||
c_line_num = line_num;
|
||||
yylval.pchar = strdup(strBfr);
|
||||
pStr = strBfr;
|
||||
if (one_line_c_code)
|
||||
{
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
<C_CODE>"}%" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
*pStr++ = 0;
|
||||
yylval.pchar = strdup(strBfr);
|
||||
BEGIN SNL;
|
||||
RETURN(C_STMT);
|
||||
}
|
||||
@@ -78,29 +83,26 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
<COMMENT>"*/" BEGIN SNL;
|
||||
<COMMENT>. ;
|
||||
<STR>"\\\"" {
|
||||
*str_next++ = yytext[0];
|
||||
*str_next++ = yytext[1];
|
||||
*pStr++ = yytext[0];
|
||||
*pStr++ = yytext[1];
|
||||
}
|
||||
<STR>\" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
*pStr++ = 0;
|
||||
yylval.pchar = strdup(strBfr);
|
||||
BEGIN SNL;
|
||||
RETURN(STRING);
|
||||
}
|
||||
<STR>. { *str_next++ = yytext[0]; }
|
||||
<STR>\n { *str_next++ = '?';
|
||||
<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} { nc = strlen(yytext);
|
||||
memcpy(str_next, yytext, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
<PP>{FPNUM} { yylval.pchar = strdup(yytext);
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<PP>\" { c_str = str_next; BEGIN PP_STR; }
|
||||
<PP>\" { pStr = strBfr; BEGIN PP_STR; }
|
||||
<PP>\n {
|
||||
BEGIN SNL;
|
||||
RETURN(CR);
|
||||
@@ -109,22 +111,22 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
<PP>. {
|
||||
}
|
||||
<PP_STR>\" {
|
||||
*str_next++ = 0;
|
||||
yylval.pchar = c_str;
|
||||
*pStr++ = 0;
|
||||
yylval.pchar = strdup(strBfr);
|
||||
BEGIN PP;
|
||||
RETURN(STRING);
|
||||
}
|
||||
<PP_STR>. { *str_next++ = yytext[0]; }
|
||||
<PP_STR>\n { *str_next++ = '?'; line_num++; }
|
||||
<PP_STR>. { *pStr++ = yytext[0]; }
|
||||
<PP_STR>\n { *pStr++ = '?'; line_num++; }
|
||||
<SNL>\n { line_num++; }
|
||||
<SNL>"%{" {
|
||||
c_str = str_next;
|
||||
pStr = strBfr;
|
||||
one_line_c_code = FALSE;
|
||||
c_line_num = line_num;
|
||||
BEGIN C_CODE;
|
||||
}
|
||||
<SNL>"%%" {
|
||||
c_str = str_next;
|
||||
pStr = strBfr;
|
||||
one_line_c_code = TRUE;
|
||||
c_line_num = line_num;
|
||||
BEGIN C_CODE;
|
||||
@@ -134,7 +136,7 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
RETURN(PP_SYMBOL);
|
||||
}
|
||||
<SNL>"/*" BEGIN COMMENT;
|
||||
<SNL>\" { c_str = str_next; BEGIN STR; }
|
||||
<SNL>\" { pStr = strBfr; BEGIN STR; }
|
||||
<SNL>"ss" RETURN(STATE_SET);
|
||||
<SNL>"state" RETURN(STATE);
|
||||
<SNL>"when" RETURN(WHEN);
|
||||
@@ -167,10 +169,7 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<SNL>{NAME} {
|
||||
nc = strlen(yytext);
|
||||
memcpy(str_next, yytext, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
yylval.pchar = strdup(yytext);
|
||||
RETURN(NAME);
|
||||
}
|
||||
<SNL>"++" RETURN(AUTO_INCR);
|
||||
@@ -217,11 +216,16 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
|
||||
<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} {
|
||||
nc = strlen(yytext);
|
||||
memcpy(str_next, yytext, nc+1);
|
||||
yylval.pchar = str_next;
|
||||
str_next += nc+1;
|
||||
yylval.pchar = strdup(yytext);
|
||||
RETURN(NUMBER);
|
||||
}
|
||||
<SNL>[\t\ ]* /* no action */ ;
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
Copyright, 1990, The Regents of the University of California.
|
||||
Los Alamos National Laboratory
|
||||
|
||||
$Id$
|
||||
snc_main.c,v 1.2 1995/06/27 15:26:11 wright Exp
|
||||
|
||||
|
||||
DESCRIPTION: Main program and miscellaneous routines for
|
||||
State Notation Compiler.
|
||||
|
||||
@@ -12,11 +14,17 @@
|
||||
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>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
@@ -33,10 +41,11 @@ int c_line_num; /* line number for beginning of C code */
|
||||
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; /* use new event flag mode */
|
||||
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
|
||||
@@ -62,7 +71,6 @@ int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FILE *infp, *outfp, *freopen();
|
||||
extern char in_file[], out_file[];
|
||||
|
||||
/* Get command arguments */
|
||||
get_args(argc, argv);
|
||||
@@ -87,17 +95,13 @@ char *argv[];
|
||||
src_file = in_file;
|
||||
|
||||
/* Use line buffered output */
|
||||
setvbuf(stdout,NULL,_IOLBF,0);
|
||||
setvbuf(stderr,NULL,_IOLBF,0);
|
||||
/* setlinebuf() isn't ANSI-C or XPG2/3/4
|
||||
setlinebuf(stdout);
|
||||
setlinebuf(stderr);
|
||||
*/
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
setvbuf(stderr, NULL, _IOLBF, 0);
|
||||
|
||||
printf("/* %s: %s */\n\n", sncVersion, in_file);
|
||||
|
||||
/* Call the SNC parser */
|
||||
yyparse();
|
||||
Global_yyparse();
|
||||
}
|
||||
/*+************************************************************************
|
||||
* NAME: get_args
|
||||
@@ -129,10 +133,11 @@ char *argv[];
|
||||
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, " -e - don't use new event flag mode\n");
|
||||
fprintf(stderr, " -v - don't include VxWorks definitions\n");
|
||||
fprintf(stderr, "example:\n snc +a -c vacuum.st\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -151,7 +156,6 @@ get_options(s)
|
||||
char *s;
|
||||
{
|
||||
int opt_val;
|
||||
extern int debug_opt, line_opt, reent_opt, warn_opt, async_opt, newef_opt;
|
||||
|
||||
if (*s == '+')
|
||||
opt_val = TRUE;
|
||||
@@ -172,6 +176,10 @@ char *s;
|
||||
debug_opt = opt_val;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
newef_opt = opt_val;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
line_opt = opt_val;
|
||||
break;
|
||||
@@ -184,8 +192,8 @@ char *s;
|
||||
warn_opt = opt_val;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
newef_opt = opt_val;
|
||||
case 'v':
|
||||
vx_opt = opt_val;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -194,17 +202,15 @@ char *s;
|
||||
}
|
||||
}
|
||||
|
||||
get_in_file(s)
|
||||
get_in_file (s)
|
||||
char *s;
|
||||
{
|
||||
extern char in_file[], out_file[];
|
||||
int ls;
|
||||
|
||||
ls = strlen(s);
|
||||
memcpy(in_file, s, ls);
|
||||
in_file[ls] = 0;
|
||||
memcpy(out_file, s, ls);
|
||||
if ( strcmp(&in_file[ls-3], ".st") == 0 )
|
||||
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;
|
||||
@@ -260,9 +266,6 @@ char *err_txt;
|
||||
yyerror(err)
|
||||
char *err;
|
||||
{
|
||||
extern char *src_file;
|
||||
extern int line_num;
|
||||
|
||||
fprintf(stderr, "%s: line no. %d (%s)\n", err, line_num, src_file);
|
||||
return;
|
||||
}
|
||||
@@ -287,8 +290,6 @@ print_line_num(line_num, src_file)
|
||||
int line_num;
|
||||
char *src_file;
|
||||
{
|
||||
extern int line_opt;
|
||||
|
||||
if (line_opt)
|
||||
printf("# line %d \"%s\"\n", line_num, src_file);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user