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