Improved delay() handling & added new language features.

This commit is contained in:
kozubal
1991-07-16 16:19:29 +00:00
parent 0a0cf9c5b7
commit b298c8dc5c
12 changed files with 450 additions and 210 deletions

View File

@@ -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("[");

View File

@@ -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,

View File

@@ -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.

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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 <stdio.h>
#include <ctype.h>
#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;
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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 <pchar> STRING
%token <pchar> C_STMT
%token IF ELSE WHILE
%token IF ELSE WHILE FOR BREAK
%token PP_SYMBOL CR
%type <ival> type
%type <pchar> subscript binop asgnop unop
%type <pexpr> state_set_list state_set state_list state transition_list transition
%type <pexpr> parameter expr
%type <pexpr> statement stmt_list compound_stmt if_stmt else_stmt while_stmt
%type <pexpr> 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); }

View File

@@ -148,6 +148,8 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
<SNL>"if" RETURN(IF);
<SNL>"else" RETURN(ELSE);
<SNL>"while" RETURN(WHILE);
<SNL>"for" RETURN(FOR);
<SNL>"break" RETURN(BREAK);
<SNL>"exit" RETURN(EXIT);
<SNL>"TRUE" { yylval.pchar = "1";
RETURN(NUMBER);
@@ -163,9 +165,11 @@ FPNUM (\-?(([0-9]+)(\.[0-9]*)?)|(\.[0-9]+))
str_next += nc+1;
RETURN(NAME);
}
<SNL>"++" RETURN(AUTO_INCR);
<SNL>"--" RETURN(AUTO_DECR);
<SNL>"||" RETURN(OR);
<SNL>"<<=" RETURN(LEFT_EQUAL);
<SNL>">>=" RETURN(RIGHT_EQUAL);
<SNL>"||" RETURN(OR);
<SNL>"&&" RETURN(AND);
<SNL>">>" RETURN(R_SHIFT);
<SNL>">=" RETURN(GE);