diff --git a/src/sequencer/gen_ss_code.c b/src/sequencer/gen_ss_code.c index 252906acc..33306b927 100644 --- a/src/sequencer/gen_ss_code.c +++ b/src/sequencer/gen_ss_code.c @@ -3,7 +3,7 @@ Copyright, 1990, The Regents of the University of California. Los Alamos National Laboratory - @(#)gen_ss_code.c 1.4 4/17/91 + $Id$ DESCRIPTION: gen_ss_code.c -- routines to generate state set code ENVIRONMENT: UNIX ***************************************************************************/ @@ -241,6 +241,21 @@ int level; /* indentation 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"); + 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"); @@ -270,6 +285,10 @@ int level; /* indentation level */ case E_STRING: printf("\"%s\"", ep->value); break; + case E_BREAK: + indent(level); + printf("break;\n"); + break; case E_FUNC: if (special_func(stmt_type, ep, sp)) break; @@ -298,6 +317,14 @@ int level; /* indentation level */ 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("["); diff --git a/src/sequencer/gen_tables.c b/src/sequencer/gen_tables.c index 1c31fc1e5..26b9223da 100644 --- a/src/sequencer/gen_tables.c +++ b/src/sequencer/gen_tables.c @@ -168,6 +168,8 @@ int index; printf("0, "); /* event id supplied by CA */ + printf("0, "); /* getSemId */ + printf("&%s", prog_name); /* ptr to state program structure */ return; @@ -256,7 +258,7 @@ gen_state_prog_table() printf("\t1,\t/* relative task priority */\n"); - printf("\t0,\t/* sem_id */\n"); + printf("\t0,\t/* caSemId */\n"); printf("\tdb_channels,\t/* *channels */\n"); @@ -320,7 +322,9 @@ gen_sscb_array() printf("\t/* State set \"%s\"*/\n", ssp->value); - printf("\t0, 1, 0,\t/* task_id, task_prioity, sem_id */\n"); + printf("\t0, 1,\t/* task_id, task_prioity */\n"); + + printf("\t0, 0,\t/* caSemId, getSemId */\n"); nstates = exprCount(ssp->left); printf("\t%d, state_%s,\t/* num_states, *states */\n", nstates, diff --git a/src/sequencer/parse.c b/src/sequencer/parse.c index 3546f3ea2..da635612d 100644 --- a/src/sequencer/parse.c +++ b/src/sequencer/parse.c @@ -4,7 +4,7 @@ Copyright, 1990, The Regents of the University of California. Los Alamos National Laboratory - @(#)parse.c 1.3 5/1/91 + $Id$ 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. diff --git a/src/sequencer/parse.h b/src/sequencer/parse.h index b7c9bc448..b80515339 100644 --- a/src/sequencer/parse.h +++ b/src/sequencer/parse.h @@ -3,7 +3,7 @@ Copyright, 1989, The Regents of the University of California. Los Alamos National Laboratory - @(#)parse.h 1.2 4/17/91 + $Id$ DESCRIPTION: Structures for parsing the state notation language. ENVIRONMENT: UNIX ***************************************************************************/ @@ -93,7 +93,7 @@ Expr *expression(), *link_expr(); #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_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: {...} */ @@ -103,3 +103,9 @@ Expr *expression(), *link_expr(); #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 index 164234819..6beecf7e3 100644 --- a/src/sequencer/phase2.c +++ b/src/sequencer/phase2.c @@ -3,7 +3,7 @@ Copyright, 1990, The Regents of the University of California. Los Alamos National Laboratory - @(#)phase2.c 1.5 4/17/91 + $Id$ DESCRIPTION: Phase 2 code generation routines for SNC. Produces code and tables in C output file. See also: gen_ss_code.c @@ -77,6 +77,7 @@ phase2() gen_preamble() { extern char *prog_name; + extern int async_flag, conn_flag, debug_flag, reent_flag; /* Program name (comment) */ printf("/* Program \"%s\" */\n", prog_name); @@ -88,6 +89,13 @@ gen_preamble() printf("\n#define NUM_SS %d\n", num_ss); printf("#define NUM_CHANNELS %d\n", num_channels); + /* #define's for compiler flags */ + gen_flag_defn(async_flag, "ASYNC_FLAG"); + gen_flag_defn(conn_flag, "CONN_FLAG" ); + gen_flag_defn(debug_flag, "DEBUG_FLAG"); + gen_flag_defn(reent_flag, "REENT_FLAG"); + printf("\n"); + /* Forward references of tables: */ printf("\nextern SPROG %s;\n", prog_name); printf("extern CHAN db_channels[];\n"); @@ -95,9 +103,20 @@ gen_preamble() return; } -int printTree = FALSE; +gen_flag_defn(flag, defn_name) +int flag; +char *defn_name; +{ + if (flag) + 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 struct */ +int printTree = FALSE; + reconcile_variables() { extern Expr *ss_list, *exit_code_list; @@ -421,6 +440,7 @@ void *argp; /* ptr to argument to pass on to function */ case E_CONST: case E_STRING: case E_TEXT: + case E_BREAK: break; case E_PAREN: @@ -431,6 +451,8 @@ void *argp; /* ptr to argument to pass on to function */ 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); @@ -443,6 +465,8 @@ void *argp; /* ptr to argument to pass on to function */ 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); @@ -453,7 +477,6 @@ void *argp; /* ptr to argument to pass on to function */ } break; - default: fprintf(stderr, "traverseExprTree: type=%d???\n", ep->type); } diff --git a/src/sequencer/seq_ca.c b/src/sequencer/seq_ca.c index c55c26246..afa94aca8 100644 --- a/src/sequencer/seq_ca.c +++ b/src/sequencer/seq_ca.c @@ -1,24 +1,50 @@ -/************************************************************************** - GTA PROJECT AT division - Copyright, 1990, The Regents of the University of California. - Los Alamos National Laboratory - - @(#)seq_ca.c 1.10 4/24/91 - DESCRIPTION: Seq_ca.c: Channel access interface for sequencer - - ENVIRONMENT: VxWorks -***************************************************************************/ +/* $Id$ + * DESCRIPTION: Channel access interface for sequencer. + * + * Author: Andy Kozubal + * Date: July, 1991 + * + * 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 07-03-91 ajk . + */ #include "seq.h" -#include "vxWorks.h" -#include "taskLib.h" + +#ifdef ANSI +LOCAL void *getPtrToValue(union db_access_val *, chtype); +#else +LOCAL void *getPtrToValue(); +#endif + /*#define DEBUG*/ #define MACRO_STR_LEN (MAX_STRING_SIZE+1) -/* Connect to the database channels through channel access */ -connect_db_channels(sp_ptr) + /* Connect to the database channels through channel access */ +seq_connect(sp_ptr) SPROG *sp_ptr; { CHAN *db_ptr; @@ -79,25 +105,26 @@ SPROG *sp_ptr; return 0; } /* Channel access events (monitors) come here */ -seq_event_handler(args) +VOID seq_event_handler(args) struct event_handler_args args; { SPROG *sp_ptr; CHAN *db_ptr; struct dbr_sts_char *dbr_sts_ptr; + void *value_ptr; int i, nbytes; /* User arg is ptr to db channel structure */ db_ptr = (CHAN *)args.usr; - /* Get ptr to data & status structure */ - dbr_sts_ptr = (struct dbr_sts_char *)args.dbr; - /* Copy value returned into user variable */ + value_ptr = getPtrToValue( + (union db_access_val *)args.dbr, db_ptr->get_type); nbytes = db_ptr->size * db_ptr->count; - bcopy(&(dbr_sts_ptr->value), db_ptr->var, nbytes); + bcopy(value_ptr, db_ptr->var, nbytes); /* Copy status & severity */ + dbr_sts_ptr = (struct dbr_sts_char *)args.dbr; db_ptr->status = dbr_sts_ptr->status; db_ptr->severity = dbr_sts_ptr->severity; @@ -107,11 +134,11 @@ struct event_handler_args args; /* Wake up each state set that is waiting for event processing */ seq_efSet(sp_ptr, 0, db_ptr->index + 1); - return 0; + return; } /* Sequencer connection handler: Called each time a connection is established or broken */ -seq_conn_handler(args) +VOID seq_conn_handler(args) struct connection_handler_args args; { CHAN *db_ptr; @@ -129,17 +156,17 @@ struct connection_handler_args args; { db_ptr->connected = FALSE; sp_ptr->conn_count--; - seqLog(sp_ptr, "Channel \"%s\" disconnected\n", db_ptr->db_name); + seq_log(sp_ptr, "Channel \"%s\" disconnected\n", db_ptr->db_name); } else { db_ptr->connected = TRUE; sp_ptr->conn_count++; - seqLog(sp_ptr, "Channel \"%s\" connected\n", db_ptr->db_name); + seq_log(sp_ptr, "Channel \"%s\" connected\n", db_ptr->db_name); if (db_ptr->count > ca_element_count(args.chid)) { db_ptr->count = ca_element_count(args.chid); - seqLog(sp_ptr, "\"%s\": reset count to %d\n", + seq_log(sp_ptr, "\"%s\": reset count to %d\n", db_ptr->db_name, db_ptr->count); } } @@ -151,9 +178,9 @@ struct connection_handler_args args; } /* Wake up each state set that is waiting for event processing */ -seq_efSet(sp_ptr, dummy, ev_flag) +VOID seq_efSet(sp_ptr, dummy, ev_flag) SPROG *sp_ptr; -void *dummy; +int dummy; int ev_flag; /* event flag */ { SSCB *ss_ptr; @@ -164,17 +191,17 @@ int ev_flag; /* event flag */ for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++) { /* Apply resource lock */ - semTake(sp_ptr->sem_id, 0); + semTake(sp_ptr->caSemId, WAIT_FOREVER); /* Test for possible event trig based on bit mask for this state */ if ( (ev_flag == 0) || bitTest(ss_ptr->pMask, ev_flag) ) { bitSet(ss_ptr->events, ev_flag); - semGive(ss_ptr->sem_id); /* wake up the ss task */ + semGive(ss_ptr->syncSemId); /* wake up the ss task */ } /* Unlock resource */ - semGive(sp_ptr->sem_id); + semGive(sp_ptr->caSemId); } } @@ -192,56 +219,43 @@ SPROG *sp_ptr; /* ptr to state program */ SSCB *ss_ptr; /* ptr to current state set */ CHAN *db_ptr; /* ptr to channel struct */ { - int status; + int status, sem_status; extern seq_callback_handler(); - extern int async_flag; /* Check for channel connected */ if (!db_ptr->connected) return ECA_DISCONN; + /* Flag this pvGet() as not completed */ db_ptr->get_complete = 0; - /* Asynchronous get? */ - if (sp_ptr->async_flag) + + /* If synchronous pvGet then clear the pvGet pend semaphore */ + if (!sp_ptr->async_flag) { - status = ca_array_get_callback( + db_ptr->getSemId = ss_ptr->getSemId; + semTake(ss_ptr->getSemId, NO_WAIT); + } + + /* Perform the CA get operation with a callback routine specified */ + status = ca_array_get_callback( db_ptr->get_type, /* db request type */ db_ptr->count, /* element count */ db_ptr->chid, /* chid */ seq_callback_handler, /* callback handler */ db_ptr); /* user arg */ - /* Note: CA buffer is not flushed */ - + if (sp_ptr->async_flag || (status != ECA_NORMAL) ) return status; - } - /* Synchronous get (wait for completion) */ - status = ca_array_get( - db_ptr->put_type, /* db request type */ - db_ptr->count, /* element count */ - db_ptr->chid, /* chid */ - db_ptr->var); /* value */ + /* Synchronous pvGet() */ - if (status == ECA_BADTYPE) - { - seqLog(sp_ptr, "Bad type: pvGet() on %s\n", db_ptr->db_name); - return status; - } + ca_flush_io(); - if (status == ECA_BADCHID) - { - seqLog(sp_ptr, "Disconencted: pvGet() on %s\n", db_ptr->db_name); - return status; - } - - /* Wait for completion */ - status = ca_pend_io(10.0); - db_ptr->get_complete = TRUE; - if (status != ECA_NORMAL) - { - seqLog(sp_ptr, "time-out: pvGet() on %s\n", db_ptr->db_name); - } + /* Wait for completion (10s timeout) */ + sem_status = semTake(ss_ptr->getSemId, 600); + if (sem_status == ERROR) + status = ECA_TIMEOUT; + return status; } @@ -253,29 +267,38 @@ struct event_handler_args args; CHAN *db_ptr; struct dbr_sts_char *dbr_sts_ptr; int i, nbytes; + void *value_ptr; /* User arg is ptr to db channel structure */ db_ptr = (CHAN *)args.usr; - /* Get ptr to data & status structure */ - dbr_sts_ptr = (struct dbr_sts_char *)args.dbr; - /* Copy value returned into user variable */ + value_ptr = getPtrToValue( + (union db_access_val *)args.dbr, db_ptr->get_type); nbytes = db_ptr->size * db_ptr->count; - bcopy(&(dbr_sts_ptr->value), db_ptr->var, nbytes); + bcopy(value_ptr, db_ptr->var, nbytes); /* Copy status & severity */ + dbr_sts_ptr = (struct dbr_sts_char *)args.dbr; db_ptr->status = dbr_sts_ptr->status; db_ptr->severity = dbr_sts_ptr->severity; /* Set get complete flag */ db_ptr->get_complete = TRUE; + /* Wake up each state set that is waiting for event processing) */ + sp_ptr = db_ptr->sprog; /* State program that owns this db entry */ + seq_efSet(sp_ptr, 0, db_ptr->index + 1); + + /* If syncronous pvGet then notify pending state set */ + if (!sp_ptr->async_flag) + semGive(db_ptr->getSemId); + return 0; } /* Flush requests */ -seq_pvFlush() +VOID seq_pvFlush() { ca_flush_io(); } @@ -295,10 +318,10 @@ CHAN *db_ptr; /* ptr to channel struct */ db_ptr->chid, db_ptr->var); if (status != ECA_NORMAL) { - seqLog(sp_ptr, "pvPut on \"%s\" failed (%d)\n", + seq_log(sp_ptr, "pvPut on \"%s\" failed (%d)\n", db_ptr->db_name, status); - seqLog(sp_ptr, " put_type=%d\n", db_ptr->put_type); - seqLog(sp_ptr, " size=%d, count=%d\n", db_ptr->size, db_ptr->count); + seq_log(sp_ptr, " put_type=%d\n", db_ptr->put_type); + seq_log(sp_ptr, " size=%d, count=%d\n", db_ptr->size, db_ptr->count); } return status; @@ -362,5 +385,36 @@ CHAN *db_ptr; /* ptr to channel struct */ db_ptr->monitored = FALSE; - return 0; + return status; } + +/* Given ptr to value structure & type, return ptr to value */ +LOCAL void *getPtrToValue(pBuf, dbrType) +union db_access_val *pBuf; +chtype dbrType; +{ + switch (dbrType) { + case DBR_STRING: return (void *)pBuf->strval; + case DBR_STS_STRING: return (void *)pBuf->sstrval.value; + + case DBR_SHORT: return (void *)&pBuf->shrtval; + case DBR_STS_SHORT: return (void *)&pBuf->sshrtval.value; + + case DBR_FLOAT: return (void *)&pBuf->fltval; + case DBR_STS_FLOAT: return (void *)&pBuf->sfltval.value; + + case DBR_ENUM: return (void *)&pBuf->enmval; + case DBR_STS_ENUM: return (void *)&pBuf->senmval.value; + + case DBR_CHAR: return (void *)&pBuf->charval; + case DBR_STS_CHAR: return (void *)&pBuf->schrval.value; + + case DBR_LONG: return (void *)&pBuf->longval; + case DBR_STS_LONG: return (void *)&pBuf->slngval.value; + + case DBR_DOUBLE: return (void *)&pBuf->doubleval; + case DBR_STS_DOUBLE: return (void *)&pBuf->sdblval.value; + default: return NULL; + } +} + diff --git a/src/sequencer/seq_mac.c b/src/sequencer/seq_mac.c index 372d3263c..85c34987d 100644 --- a/src/sequencer/seq_mac.c +++ b/src/sequencer/seq_mac.c @@ -3,19 +3,31 @@ Copyright, 1990, The Regents of the University of California. Los Alamos National Laboratory - @(#)seq_mac.c 1.3 4/23/91 + $Id$ DESCRIPTION: Macro routines for Sequencer. ENVIRONMENT: VxWorks ***************************************************************************/ -#include -#include -#include "vxWorks.h" #include "seq.h" +#ifdef ANSI +LOCAL int macNameLth(char *); +LOCAL int seqMacParseName(char *); +LOCAL int seqMacParseValue(char *); +LOCAL char *skipBlanks(char *); +LOCAL MACRO *seqMacTblGet(char *, MACRO *); +#else +LOCAL int macNameLth(); +LOCAL int seqMacParseName(); +LOCAL int seqMacParseValue(); +LOCAL char *skipBlanks(); +LOCAL MACRO *seqMacTblGet(); +#endif + + /*#define DEBUG*/ -/* seqMacTblInit - initialize macro table */ + /* seqMacTblInit - initialize macro table */ seqMacTblInit(mac_ptr) MACRO *mac_ptr; { diff --git a/src/sequencer/seq_main.c b/src/sequencer/seq_main.c index 6c3e80c40..0dab46979 100644 --- a/src/sequencer/seq_main.c +++ b/src/sequencer/seq_main.c @@ -3,7 +3,7 @@ Copyright, 1990, The Regents of the University of California. Los Alamos National Laboratory - @(#)seq_main.c 1.2 4/23/91 + $Id$ DESCRIPTION: Seq() initiates a sequence as a group of cooperating tasks. An optional string parameter specifies the values for macros. @@ -11,14 +11,34 @@ ENVIRONMENT: VxWorks HISTORY: - 23apr91,ajk Fixed problem with state program invoking the sequencer. +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() or + semMCreate(). Modified semTake() second param. to WAIT_FOREVER. + These provide VX5.0 compatability. ***************************************************************************/ - /*#define DEBUG 1*/ #include "seq.h" -#include "vxWorks.h" -#include "taskLib.h" + +#define ANSI + +#ifdef ANSI +/* ANSI functional prototypes */ +LOCAL SPROG *alloc_task_area(SPROG *); +LOCAL VOID copy_sprog(SPROG *, SPROG *); +LOCAL VOID init_sprog(SPROG *); +LOCAL VOID init_sscb(SPROG *); +LOCAL VOID seq_logInit(SPROG *); + +#else +/* Archaic (i.e. Sun) functional prototypes */ +LOCAL SPROG *alloc_task_area(); +LOCAL VOID copy_sprog(); +LOCAL VOID init_sprog(); +LOCAL VOID init_sscb(); +LOCAL VOID seq_logInit(); +#endif #define SCRATCH_SIZE (MAX_MACROS*(MAX_STRING_SIZE+1)*12) @@ -33,8 +53,8 @@ */ SPROG *seq_task_ptr = NULL; -/* User entry routine to initiate a state program */ -seq(sp_ptr_orig, macro_def, stack_size) + /* User-callable routine to initiate a state program */ +int seq(sp_ptr_orig, macro_def, stack_size) SPROG *sp_ptr_orig; /* ptr to original state program table */ char *macro_def; /* macro def'n string */ int stack_size; /* stack size */ @@ -92,12 +112,9 @@ int stack_size; /* stack size */ /* Parse the macro definitions from the command line */ seqMacParse(macro_def, sp_ptr); -#ifdef DEBUG - print_macro_defs(sp_ptr->mac_ptr); -#endif DEBUG /* Initialize sequencer logging */ - seqLogInit(sp_ptr); + seq_logInit(sp_ptr); /* Specify stack size */ pname = "stack"; @@ -118,33 +135,17 @@ int stack_size; /* stack size */ ptask_name = sp_ptr->name; /* Spawn the sequencer main task */ - seqLog(sp_ptr, "Spawning state program \"%s\", task name = \"%s\"\n", + seq_log(sp_ptr, "Spawning state program \"%s\", task name = \"%s\"\n", sp_ptr->name, ptask_name); status = taskSpawn(ptask_name, SPAWN_PRIORITY, SPAWN_OPTIONS, stack_size, sequencer, sp_ptr, stack_size, ptask_name); - seqLog(sp_ptr, " Task id = %d = 0x%x\n", status, status); + seq_log(sp_ptr, " Task id = %d = 0x%x\n", status, status); return status; } #ifdef DEBUG -print_macro_defs(mac_ptr) -MACRO *mac_ptr; -{ - int i; - - printf("Macro definitions:\n"); - - for (i = 0; i < MAX_MACROS; i++, mac_ptr++) - { - if (mac_ptr->name != NULL) - { - printf(" %s = %s\n", mac_ptr->name, mac_ptr->value); - } - } -} - print_sp_info(sp_ptr) SPROG *sp_ptr; { @@ -265,7 +266,7 @@ SPROG *sp_ptr_orig; /* original state program structure */ /* Copy the SSCB, STATE, and CHAN structures into this task. Note: we have to change the pointers in the SPROG struct, user variables, and all SSCB structs */ -LOCAL copy_sprog(sp_ptr_orig, sp_ptr) +LOCAL VOID copy_sprog(sp_ptr_orig, sp_ptr) SPROG *sp_ptr_orig; /* original ptr to program struct */ SPROG *sp_ptr; /* new ptr */ { @@ -318,16 +319,14 @@ SPROG *sp_ptr; /* new ptr */ /* Note: user area is not copied; it should be all zeros */ - return 0; + return; } /* Initialize state program block */ -LOCAL init_sprog(sp_ptr) +LOCAL VOID init_sprog(sp_ptr) SPROG *sp_ptr; { - /* Semaphore for resource locking on events */ - sp_ptr->sem_id = semCreate(); - semInit(sp_ptr->sem_id); - semGive(sp_ptr->sem_id); + /* Semaphore for resource locking on CA events */ + sp_ptr->caSemId = semMCreate(SEM_INVERSION_SAFE | SEM_DELETE_SAFE); sp_ptr->task_is_deleted = FALSE; sp_ptr->logFd = 0; @@ -336,7 +335,7 @@ SPROG *sp_ptr; } /* Initialize state set control blocks */ -LOCAL init_sscb(sp_ptr) +LOCAL VOID init_sscb(sp_ptr) SPROG *sp_ptr; { SSCB *ss_ptr; @@ -346,16 +345,15 @@ SPROG *sp_ptr; for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++) { ss_ptr->task_id = 0; - ss_ptr->sem_id = semCreate(); - semInit(ss_ptr->sem_id); - semGive(ss_ptr->sem_id); + /* Create a binary semaphore for synchronizing events in a SS */ + ss_ptr->syncSemId = semBCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE); ss_ptr->current_state = 0; /* initial state */ ss_ptr->next_state = 0; ss_ptr->action_complete = TRUE; for (i = 0; i < NWRDS; i++) ss_ptr->events[i] = 0; /* clear events */ } - return 0; + return; } /* Allocate memory from scratch area (always round up to even no. bytes) */ @@ -379,16 +377,14 @@ int nChar; return NULL; } /* Initialize logging */ -seqLogInit(sp_ptr) +LOCAL VOID seq_logInit(sp_ptr) SPROG *sp_ptr; { char *pname, *pvalue, *seqMacValGet(); int fd; - /* Create a resource locking semaphore */ - sp_ptr->logSemId = semCreate(); - semInit(sp_ptr->logSemId); - semGive(sp_ptr->logSemId); + /* Create a logging resource locking semaphore */ + sp_ptr->logSemId = semMCreate(SEM_INVERSION_SAFE | SEM_DELETE_SAFE); sp_ptr->logFd = ioGlobalStdGet(1); /* default fd is std out */ @@ -404,9 +400,9 @@ SPROG *sp_ptr; } } -/* Log a message to the console or a file with time of day and task id */ + /* Log a message to the console or a file with time of day and task id */ #include "tsDefs.h" -seqLog(sp_ptr, fmt, arg1, arg2, arg3, arg4, arg5, arg6) +VOID seq_log(sp_ptr, fmt, arg1, arg2, arg3, arg4, arg5, arg6) SPROG *sp_ptr; char *fmt; /* format string */ int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */ @@ -423,8 +419,8 @@ int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */ /* Truncate the .nano-secs part */ timeBfr[17] = 0; - /* Lock seqLog resource */ - semTake(sp_ptr->logSemId, 0); + /* Lock seq_log resource */ + semTake(sp_ptr->logSemId, WAIT_FOREVER); /* Print the message: e.g. "10:23:28 T13: ...." */ fd = sp_ptr->logFd; @@ -440,5 +436,54 @@ int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */ ioctl(fd, FIOSYNC); } - return 0; + return; } +/* seqLog() - State program interface to seq_log() */ +VOID seqLog(fmt, arg1, arg2, arg3, arg4, arg5, arg6) +char *fmt; /* format string */ +int arg1, arg2, arg3, arg4, arg5, arg6; /* arguments */ +{ + extern SPROG *seq_task_ptr; + + if (seq_task_ptr == ERROR) + return; + seq_log(seq_task_ptr, fmt, arg1, arg2, arg3, arg4, arg5, arg6); +} + + /* seq_flagGet: get the value of a flag ("-" -> FALSE; "+" -> TRUE) */ +BOOL seq_flagGet(sp_ptr, flag) +SPROG *sp_ptr; +char *flag; /* one of the snc flags as a strign (e.g. "a") */ +{ + switch (flag[0]) + { + case 'a': return sp_ptr->async_flag; + case 'c': return sp_ptr->conn_flag; + case 'd': return sp_ptr->debug_flag; + case 'r': return sp_ptr->reent_flag; + default: return FALSE; + } +} + +#ifdef VX4 +/* Fake Vx5.0 semaphore creation */ +SEM_ID semMCreate(flags) +int flags; +{ + SEM_ID semId; + + semId = semCreate(); + semInit(semId); + semGive(semId); + return(semId); +} +SEM_ID semBCreate(flags) +int flags; +{ + SEM_ID semId; + + semId = semCreate(); + semInit(semId); + return(semId); +} +#endif VX4 diff --git a/src/sequencer/seq_qry.c b/src/sequencer/seq_qry.c index f72b3b458..1288f61d7 100644 --- a/src/sequencer/seq_qry.c +++ b/src/sequencer/seq_qry.c @@ -14,11 +14,24 @@ /* #define DEBUG 1 */ #include "seq.h" -#include "vxWorks.h" -#include "taskLib.h" + +#define ANSI +#ifdef ANSI +int seqShow(int); +int seqChanShow(int); +LOCAL VOID wait_rtn(); +static void printValue(void *, int, int, int); +static void printType(int); +#else +int seqShow(); +int seqChanShow(); +LOCAL VOID wait_rtn(); +static void printValue(); +static void printType(); +#endif /* Querry the sequencer for state information */ -seqShow(tid) +int seqShow(tid) int tid; { extern SPROG *seq_task_ptr; @@ -94,7 +107,7 @@ int tid; return 0; } /* Querry the sequencer for channel information */ -seqChanShow(tid) +int seqChanShow(tid) int tid; { extern SPROG *seq_task_ptr; @@ -131,7 +144,7 @@ int tid; printf(" Size=%d bytes\n", db_ptr->size); printf(" Count=%d\n", db_ptr->count); printType(db_ptr->put_type); - printValue(db_ptr->var, db_ptr->size, db_ptr->count, + printValue((void *)db_ptr->var, db_ptr->size, db_ptr->count, db_ptr->put_type); printf(" DB get request type=%d\n", db_ptr->get_type); printf(" DB put request type=%d\n", db_ptr->put_type); @@ -164,7 +177,7 @@ int tid; } -wait_rtn() +LOCAL VOID wait_rtn() { char bfr; printf("Hit RETURN to continue\n"); @@ -183,7 +196,7 @@ struct dbr_union { } u; }; -static printValue(pvar, size, count, type) +static void printValue(pvar, size, count, type) void *pvar; int size, count, type; { @@ -228,7 +241,7 @@ int size, count, type; printf("\n"); } -static printType(type) +static void printType(type) int type; { char *type_str; @@ -261,4 +274,3 @@ int type; } printf(" Type = %s\n", type_str); } - diff --git a/src/sequencer/seq_task.c b/src/sequencer/seq_task.c index 4ed67c9e0..a6e7b1a41 100644 --- a/src/sequencer/seq_task.c +++ b/src/sequencer/seq_task.c @@ -11,10 +11,21 @@ ***************************************************************************/ #include "seq.h" -#include "vxWorks.h" -#include "taskLib.h" + +/* Function declarations */ +#define ANSI +#ifdef ANSI +LOCAL VOID ss_task_init(SPROG *, SSCB *); +LOCAL long get_timeout(SSCB *); +#else +LOCAL VOID ss_task_init(); +LOCAL long get_timeout(); +#endif ANSI #define TASK_NAME_SIZE 10 + +#define MAX_TIMEOUT (1<<30) /* like 2 years */ + /* Sequencer main task entry point */ sequencer(sp_ptr, stack_size, ptask_name) SPROG *sp_ptr; /* ptr to original (global) state program table */ @@ -33,7 +44,7 @@ char *ptask_name; /* Parent task name */ /* Make "seq_task_ptr" a task variable */ if (taskVarAdd(sp_ptr->task_id, &seq_task_ptr) != OK) { - seqLog(sp_ptr, "%s: taskVarAdd failed\n", sp_ptr->name); + seq_log(sp_ptr, "%s: taskVarAdd failed\n", sp_ptr->name); return -1; } seq_task_ptr = sp_ptr; @@ -49,7 +60,7 @@ char *ptask_name; /* Parent task name */ /* Connect to database channels & initiate monitor requests. Returns here immediately if "connect" switch is not set */ - connect_db_channels(sp_ptr); + seq_connect(sp_ptr); /* Create the state set tasks */ if (strlen(ptask_name) > TASK_NAME_SIZE); @@ -66,7 +77,7 @@ char *ptask_name; /* Parent task name */ SPAWN_PRIORITY+ss_ptr->task_priority, SPAWN_OPTIONS, stack_size, ss_entry, sp_ptr, ss_ptr); - seqLog(sp_ptr, "Spawning task %d: \"%s\"\n", task_id, task_name); + seq_log(sp_ptr, "Spawning task %d: \"%s\"\n", task_id, task_name); } /* Main task handles first state set */ @@ -74,13 +85,13 @@ char *ptask_name; /* Parent task name */ } /* Task entry point for state sets */ /* Provides main loop for state set processing (common, re-entrant code) */ -ss_entry(sp_ptr, ss_ptr) +VOID ss_entry(sp_ptr, ss_ptr) SPROG *sp_ptr; SSCB *ss_ptr; { BOOL ev_trig; STATE *st_ptr, *st_pNext; - ULONG delay, get_timeout(); + long delay; int i; char *var_ptr; @@ -96,10 +107,10 @@ SSCB *ss_ptr; while (1) { /* Clear event bits */ - semTake(sp_ptr->sem_id, 0); /* Lock CA */ + semTake(sp_ptr->caSemId, WAIT_FOREVER); /* Lock CA event update */ for (i = 0; i < NWRDS; i++) ss_ptr->events[i] = 0; - semGive(sp_ptr->sem_id); /* Unlock CA */ + semGive(sp_ptr->caSemId); /* Unlock CA event update */ ss_ptr->time = tickGet(); /* record time we entered this state */ @@ -108,27 +119,23 @@ SSCB *ss_ptr; st_ptr->delay_func(sp_ptr, ss_ptr, var_ptr); /* On 1-st pass fall thru w/o wake up */ - semGive(ss_ptr->sem_id); + semGive(ss_ptr->syncSemId); /* Loop until an event is triggered */ do { /* Wake up on CA event, event flag, or expired time delay */ - semTake(ss_ptr->sem_id, get_timeout(ss_ptr, st_ptr)); -#ifdef DEBUG - printf("%s: semTake returned, events[0]=0x%x\n", - ss_ptr->name, ss_ptr->events[0]); -#endif DEBUG - ss_ptr->time = tickGet(); + delay = get_timeout(ss_ptr); + semTake(ss_ptr->syncSemId, delay); - /* Apply CA resource lock: any new events coming in will - be deferred until after event tests */ - semTake(sp_ptr->sem_id, 0); + /* Apply resource lock: any new events coming in will + be deferred until next state is entered */ + semTake(sp_ptr->caSemId, WAIT_FOREVER); /* Call event function to check for event trigger */ ev_trig = st_ptr->event_func(sp_ptr, ss_ptr, var_ptr); /* Unlock CA resource */ - semGive(sp_ptr->sem_id); + semGive(sp_ptr->caSemId); } while (!ev_trig); /* Event triggered */ @@ -152,7 +159,7 @@ SSCB *ss_ptr; } } /* Initialize state-set tasks */ -LOCAL ss_task_init(sp_ptr, ss_ptr) +LOCAL VOID ss_task_init(sp_ptr, ss_ptr) SPROG *sp_ptr; SSCB *ss_ptr; { @@ -168,31 +175,33 @@ SSCB *ss_ptr; return; } - /* Return time-out for semTake() */ -LOCAL ULONG get_timeout(ss_ptr) + /* Return time-out for delay() */ +LOCAL long get_timeout(ss_ptr) SSCB *ss_ptr; { - int ndelay; - ULONG time, timeout, tmin; + int ndelay; + long timeout; /* min. expiration clock time */ + long delay; /* min. delay (tics) */ if (ss_ptr->ndelay == 0) - return 0; + return MAX_TIMEOUT; - time = tickGet(); - tmin = 0; - /* find lowest timeout that's not expired */ + timeout = MAX_TIMEOUT; /* start with largest timeout */ + + /* Find the minimum abs. timeout (0 means already expired) */ for (ndelay = 0; ndelay < ss_ptr->ndelay; ndelay++) { - timeout = ss_ptr->timeout[ndelay]; - if (time < timeout) - { - if (tmin == 0 || timeout < tmin) - tmin = timeout; - } + if ((ss_ptr->timeout[ndelay] != 0) && + (ss_ptr->timeout[ndelay] < timeout) ) + timeout = (long)ss_ptr->timeout[ndelay]; } - if (tmin != 0) - tmin -= time; /* convert timeout to delay */ - return tmin; + + /* Convert timeout to delay */ + delay = timeout - tickGet(); + if (delay <= 0) + return NO_WAIT; + else + return delay; } /* Set-up for delay() on entering a state. This routine is called by the state program for each delay in the "when" statement */ @@ -220,9 +229,31 @@ SPROG *sp_ptr; SSCB *ss_ptr; int delay_id; { - return (ss_ptr->time >= ss_ptr->timeout[delay_id]); + if (ss_ptr->timeout[delay_id] == 0) + return TRUE; /* previously expired t-o */ + + if (tickGet() >= ss_ptr->timeout[delay_id]) + { + ss_ptr->timeout[delay_id] = 0; /* mark as expired */ + return TRUE; + } + return FALSE; } - /* This task is run whenever ANY task in the system is deleted */ + /* + * Delete the state set tasks and do general clean-up. + * General procedure is: + * 1. Suspend all state set tasks except self. + * 2. Call the user program's exit routine. + * 3. Delete all state set tasks except self. + * 4. Delete semaphores, close log file, and free allocated memory. + * 5. Return, causing self to be deleted. + * + * This task is run whenever ANY task in the system is deleted. + * Therefore, we have to check the task variable "seq_task_ptr" + * to see if it's one of ours. + * With VxWorks 5.0 we need to change references to the TCBX to handle + * the Wind kernel. + */ sprog_delete(pTcbX) TCBX *pTcbX; /* ptr to TCB of task to be deleted */ { @@ -247,20 +278,16 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ return -1; } - /* Suspend state set tasks */ + /* Suspend all state set tasks except self */ ss_ptr = sp_ptr->sscb; for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++) { tid_ss = ss_ptr->task_id; - if ( tid_ss > 0) + if ( (tid_ss > 0) && (tid != tid_ss) ) { - /* Don't suspend self */ - if (tid != tid_ss) - { - logMsg(" suspend ss task: tid=%d\n", tid_ss); - taskVarSet(tid_ss, &seq_task_ptr, ERROR); - taskSuspend(tid_ss); - } + logMsg(" suspend ss task: tid=%d\n", tid_ss); + taskVarSet(tid_ss, &seq_task_ptr, ERROR); + taskSuspend(tid_ss); } } @@ -275,26 +302,27 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ sp_ptr->logFd = ioGlobalStdGet(1); } - /* Delete state set tasks & delete semaphores */ + /* Delete state set tasks (except self) & delete their semaphores */ ss_ptr = sp_ptr->sscb; for (nss = 0; nss < sp_ptr->nss; nss++, ss_ptr++) { tid_ss = ss_ptr->task_id; if ( tid_ss > 0) { - /* Don't delete self */ if (tid != tid_ss) { logMsg(" delete ss task: tid=%d\n", tid_ss); taskVarSet(tid_ss, &seq_task_ptr, ERROR); taskDelete(tid_ss); } - semDelete(ss_ptr->sem_id); + semDelete(ss_ptr->syncSemId); + if (!sp_ptr->async_flag) + semDelete(ss_ptr->getSemId); } } - /* Delete semaphores & free the task area */ - semDelete(sp_ptr->sem_id); + /* Delete program-wide semaphores & free the task area */ + semDelete(sp_ptr->caSemId); semDelete(sp_ptr->logSemId); logMsg("free sp_ptr->dyn_ptr=0x%x\n", sp_ptr->dyn_ptr); taskDelay(5); @@ -302,13 +330,23 @@ TCBX *pTcbX; /* ptr to TCB of task to be deleted */ return 0; } - /* semTake - take semaphore: - VxWorks semTake with timeout added. */ -LOCAL VOID semTake (semId, timeout) -SEM_ID semId; /* semaphore id to take */ -UINT timeout; /* timeout in tics */ -{ - int dummy; + /* VxWorks Version 4.02 only */ +#ifdef VX4 - vrtxPend(&semId->count, timeout, &dummy); +/* seq_semTake - take semaphore: + * VxWorks semTake() with timeout added. (emulates VxWorks 5.0) + */ +VOID seq_semTake(semId, timeout) +SEM_ID semId; /* semaphore id to take */ +long timeout; /* timeout in tics */ +{ + int dummy; + + if (timeout == WAIT_FOREVER) + vrtxPend(&semId->count, 0, &dummy); + else if (timeout == NO_WAIT) + semClear(semId); + else + vrtxPend(&semId->count, timeout, &dummy); } +#endif VX4 diff --git a/src/sequencer/snc.y b/src/sequencer/snc.y index 3bb4ddab0..04492ee8a 100644 --- a/src/sequencer/snc.y +++ b/src/sequencer/snc.y @@ -4,7 +4,7 @@ Copyright, 1990, The Regents of the University of California. Los Alamos National Laboratory - @(#)snc.y 1.2 4/17/91 + $Id$ ENVIRONMENT: UNIX ***************************************************************************/ /* SNC - State Notation Compiler. @@ -54,19 +54,21 @@ extern int line_num; /* input file line no. */ %token MONITOR ASSIGN TO WHEN 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 +%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 parameter expr %type statement stmt_list compound_stmt if_stmt else_stmt while_stmt +%type for_stmt /* precidence rules for expr evaluation */ %left OR AND %left GT GE EQ NE LE LT @@ -188,6 +190,10 @@ expr /* general expr: e.g. (-b+2*a/(c+d)) != 0 || (func1(x,y) < 5.0) */ : expr binop expr { $$ = expression(E_BINOP, $2, $1, $3); } | expr asgnop expr { $$ = expression(E_ASGNOP, $2, $1, $3); } | unop expr %prec UOP { $$ = expression(E_UNOP, $1, $2, 0); } +| AUTO_INCR expr %prec UOP { $$ = expression(E_PRE, "++", $2, 0); } +| AUTO_DECR expr %prec UOP { $$ = expression(E_PRE, "--", $2, 0); } +| expr AUTO_INCR %prec UOP { $$ = expression(E_POST, "++", $1, 0); } +| expr AUTO_DECR %prec UOP { $$ = expression(E_POST, "--", $1, 0); } | NUMBER { $$ = expression(E_CONST, $1, 0, 0); } | STRING { $$ = expression(E_STRING, $1, 0, 0); } | NAME { $$ = expression(E_VAR, $1, 0, 0); } @@ -226,6 +232,7 @@ binop /* Binary operators */ | BIT_AND { $$ = "&"; } | COMPLEMENT { $$ = "^"; } | MODULO { $$ = "%"; } +| COMMA { $$ = ","; } ; asgnop /* Assignment operators */ @@ -261,10 +268,12 @@ stmt_list statement : compound_stmt { $$ = $1; } -| expr SEMI_COLON { $$ = expression(E_STMT, "",$1, 0); } +| expr SEMI_COLON { $$ = expression(E_STMT, "", $1, 0); } +| BREAK SEMI_COLON { $$ = expression(E_BREAK, "", 0, 0); } | if_stmt { $$ = $1; } | else_stmt { $$ = $1; } | while_stmt { $$ = $1; } +| for_stmt { $$ = $1; } | C_STMT { $$ = expression(E_TEXT, "", $1, 0); } | pp_code { $$ = 0; } | error { snc_err("action statement"); } @@ -282,6 +291,12 @@ while_stmt : WHILE L_PAREN expr R_PAREN statement { $$ = expression(E_WHILE, "", $3, $5); } ; +for_stmt +: FOR L_PAREN expr SEMI_COLON expr SEMI_COLON expr R_PAREN statement + { $$ = expression(E_FOR, "", expression(E_X, "", $3, $5), + expression(E_X, "", $7, $9) ); } +; + pp_code /* pre-processor code (e.g. # 1 "test.st") */ : PP_SYMBOL NUMBER STRING CR { pp_code($2, $3, ""); } | PP_SYMBOL NUMBER STRING NUMBER CR { pp_code($2, $3, $4); } diff --git a/src/sequencer/snc_lex.l b/src/sequencer/snc_lex.l index 704f23c49..4043819ba 100644 --- a/src/sequencer/snc_lex.l +++ b/src/sequencer/snc_lex.l @@ -148,6 +148,8 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+)) "if" RETURN(IF); "else" RETURN(ELSE); "while" RETURN(WHILE); +"for" RETURN(FOR); +"break" RETURN(BREAK); "exit" RETURN(EXIT); "TRUE" { yylval.pchar = "1"; RETURN(NUMBER); @@ -163,9 +165,11 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+)) str_next += nc+1; RETURN(NAME); } +"++" RETURN(AUTO_INCR); +"--" RETURN(AUTO_DECR); +"||" RETURN(OR); "<<=" RETURN(LEFT_EQUAL); ">>=" RETURN(RIGHT_EQUAL); -"||" RETURN(OR); "&&" RETURN(AND); ">>" RETURN(R_SHIFT); ">=" RETURN(GE);