copy from other repository

This commit is contained in:
zimoch
2010-09-02 14:52:17 +00:00
parent 35768cbfbb
commit d37c142d36
51 changed files with 4104 additions and 0 deletions

25
srcSynApps/Makefile Normal file
View File

@ -0,0 +1,25 @@
TOP=../..
include $(TOP)/configure/CONFIG
-include ../src/CONFIG_STREAM
-include ../../src/CONFIG_STREAM
LIBRARY_DEFAULT = streamSynApps
DBD += $(LIBRARY_DEFAULT).dbd
ifeq ($(LOADABLE_MODULE),YES)
SRCS += $(LIBRARY_DEFAULT)_registerRecordDeviceDriver.cpp
endif
SRCS += $(SYNAPPS_RECORDS:%=dev%Stream.c)
LIB_LIBS += stream $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES
# create streamSynApps.dbd from all SYNAPPS_RECORDS
$(COMMON_DIR)/$(LIBRARY_DEFAULT).dbd: ../../src/CONFIG_STREAM
@for r in $(SYNAPPS_RECORDS); \
do echo "device($$r,INST_IO,dev$${r}Stream,\"stream\")"; \
done > $@

View File

@ -0,0 +1,108 @@
/***************************************************************
* Stream Device record interface for scalcout records *
* *
* (C) 2006 Dirk Zimoch (dirk.zimoch@psi.ch) *
* *
* This is an EPICS record Interface for StreamDevice. *
* Please refer to the HTML files in ../doc/ for a detailed *
* documentation. *
* *
* If you do any changes in this file, you are not allowed to *
* redistribute it any more. If there is a bug or a missing *
* feature, send me an email and/or your patch. If I accept *
* your changes, they will go to the next release. *
* *
* DISCLAIMER: If this software breaks something or harms *
* someone, it's your problem. *
* *
***************************************************************/
#include <devStream.h>
#include <sCalcoutRecord.h>
#include <epicsExport.h>
/* scalcout record has a bug: it never calls init_record
of the device support.
Fix: sCalcoutRecord.c, end of init_record() add
if(pscalcoutDSET->init_record ) {
return (*pscalcoutDSET->init_record)(pcalc);
}
The bug has been fixed in version 2-6-1.
*/
static long readData (dbCommon *record, format_t *format)
{
scalcoutRecord *sco = (scalcoutRecord *) record;
switch (format->type)
{
case DBF_DOUBLE:
{
return streamScanf (record, format, &sco->val);
}
case DBF_LONG:
case DBF_ENUM:
{
long lval;
if (streamScanf (record, format, &lval)) return ERROR;
sco->val = lval;
return OK;
}
case DBF_STRING:
{
return (streamScanfN (record, format,
sco->sval, sizeof(sco->val)));
}
}
return ERROR;
}
static long writeData (dbCommon *record, format_t *format)
{
scalcoutRecord *sco = (scalcoutRecord *) record;
switch (format->type)
{
case DBF_DOUBLE:
{
return streamPrintf (record, format, sco->oval);
}
case DBF_LONG:
case DBF_ENUM:
{
return streamPrintf (record, format, (long)sco->oval);
}
case DBF_STRING:
{
return streamPrintf (record, format, sco->osv);
}
}
return ERROR;
}
static long initRecord (dbCommon *record)
{
scalcoutRecord *sco = (scalcoutRecord *) record;
return streamInitRecord (record, &sco->out, readData, writeData);
}
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write;
} devscalcoutStream = {
5,
streamReport,
streamInit,
initRecord,
streamGetIointInfo,
streamWrite,
};
epicsExportAddress(dset,devscalcoutStream);

4
streamApp/.cvsignore Normal file
View File

@ -0,0 +1,4 @@
StreamDebug.log
streamApp
streamApp.exe*
TS.*

76
streamApp/Makefile Normal file
View File

@ -0,0 +1,76 @@
TOP=../..
# Look if we have EPICS R3.13 or R3.14
ifeq ($(wildcard $(TOP)/configure),)
# EPICS R3.13
include $(TOP)/config/CONFIG_APP
# The real work is in Makefile.Vx
include $(TOP)/config/RULES_ARCHS
else
# EPICS R3.14
include $(TOP)/configure/CONFIG
#HOST_OPT = NO
PROD = streamApp
DBD = streamApp.dbd
streamApp_DBD += base.dbd
#streamApp_DBD += aaiRecord.dbd aaoRecord.dbd
PROD_SRCS += streamApp_registerRecordDeviceDriver.cpp
PROD_SRCS_DEFAULT = streamAppMain.cc
PROD_SRCS_vxWorks = -nil-
PROD_LIBS = stream
ifdef PCRE
# With local PCRE package
PROD_LIBS += pcre
else
ifneq ($(words $(PCRE_LIB) $(PCRE_INCLUDE)),0)
# With system wide PCRE installation
PROD_SYS_LIBS += pcre
PROD_DEPLIB_DIRS += $(PCRE_LIB)
endif
endif
ifdef ASYN
# Which types of asyn busses do you have?
ifneq ($(OS_CLASS), WIN32)
# asynDriver up to version 4-8 does not support serial port for Windows!
streamApp_DBD += drvAsynSerialPort.dbd
endif
streamApp_DBD += drvAsynIPPort.dbd
#streamApp_DBD += drvGsIP488.dbd
#streamApp_DBD += drvNi1014.dbd
streamApp_DBD += drvVxi11.dbd
PROD_LIBS += asyn
endif
ifneq ($(words $(CALC) $(SYNAPPS)), 0)
# With synApps scalcout record
streamApp_DBD += calc.dbd
streamApp_DBD += streamSynApps.dbd
PROD_LIBS += calc sscan
PROD_LIBS_DEFAULT += streamSynApps
endif
streamApp_DBD += stream.dbd
PROD_LIBS += $(EPICS_BASE_IOC_LIBS)
# Write StreamDevice debug output to this file
CPPFLAGS += -DDEBUGFILE=StreamDebug.log
include $(TOP)/configure/RULES
clean:: myclean
myclean:
rm -f core* StreamDebug.log
endif

8
streamApp/Makefile.Host Normal file
View File

@ -0,0 +1,8 @@
TOP = ../../..
include $(TOP)/config/CONFIG_APP
DBDEXPAND = streamAppInclude-3-13.dbd
DBDNAME = streamApp.dbd
include $(TOP)/config/RULES.Host

20
streamApp/Makefile.Vx Normal file
View File

@ -0,0 +1,20 @@
TOP = ../../..
include $(TOP)/config/CONFIG_APP
LIBNAME = streamApp
LDLIBS += $(COMPAT_BIN)/compatLib
LDLIBS += $(ASYN_BIN)/asynLib
LDLIBS += $(INSTALL_BIN)/streamLib
include ../base-3-13LIBOBJS
# Write StreamDevice debug output to this file
CPPFLAGS += -DDEBUGFILE=StreamDebug.log
include $(TOP)/config/RULES.Vx
include $(TOP)/config/RULES.munch
# Rebuild when LIBOBJS change
$(LIBNAME): ../base-3-13LIBOBJS

242
streamApp/base-3-13.dbd Normal file
View File

@ -0,0 +1,242 @@
include "menuGlobal.dbd"
include "menuConvert.dbd"
include "aiRecord.dbd"
include "aaiRecord.dbd"
include "aoRecord.dbd"
include "aaoRecord.dbd"
include "biRecord.dbd"
include "boRecord.dbd"
include "calcRecord.dbd"
include "calcoutRecord.dbd"
include "compressRecord.dbd"
include "dfanoutRecord.dbd"
#include "egRecord.dbd"
#include "egeventRecord.dbd"
#include "erRecord.dbd"
#include "ereventRecord.dbd"
include "eventRecord.dbd"
include "fanoutRecord.dbd"
#include "histogramRecord.dbd"
include "longinRecord.dbd"
include "longoutRecord.dbd"
include "mbbiRecord.dbd"
include "mbbiDirectRecord.dbd"
include "mbboRecord.dbd"
include "mbboDirectRecord.dbd"
include "permissiveRecord.dbd"
#include "pidRecord.dbd"
#include "pulseCounterRecord.dbd"
#include "pulseDelayRecord.dbd"
#include "pulseTrainRecord.dbd"
#include "scanRecord.dbd"
include "selRecord.dbd"
include "seqRecord.dbd"
include "stateRecord.dbd"
#include "steppermotorRecord.dbd"
include "stringinRecord.dbd"
include "stringoutRecord.dbd"
include "subRecord.dbd"
#include "gsubRecord.dbd"
#include "palRecord.dbd"
include "subArrayRecord.dbd"
#include "timerRecord.dbd"
#include "waitRecord.dbd"
include "waveformRecord.dbd"
device(ai,CONSTANT,devAiSoft,"Soft Channel")
device(ai,CONSTANT,devAiSoftRaw,"Raw Soft Channel")
#device(ai,VME_IO,devAiXy566Se,"XYCOM-566 SE Scanned")
#device(ai,VME_IO,devAiXy566Di,"XYCOM-566 Dif Scanned")
#device(ai,VME_IO,devAiXy566DiL,"XYCOM-566 Dif Latched")
#device(ai,VME_IO,devAiDvx2502,"DVX-2502")
#device(ai,CONSTANT,devAiTestAsyn,"Test Asyn")
#device(ai,AB_IO,devAiAb1771Il,"AB-1771IL-Analog In")
#device(ai,AB_IO,devAiAb1771Ife,"AB-1771IFE")
#device(ai,AB_IO,devAiAb1771Ixe,"AB-1771IXE-Millivolt In")
#device(ai,AB_IO,devAiAb1771IfeSe,"AB-1771IFE-SE")
#device(ai,AB_IO,devAiAb1771IfeMa,"AB-1771IFE-4to20MA")
#device(ai,AB_IO,devAiAb1771Ife0to5V,"AB-1771IFE-0to5Volt")
#device(ai,AB_IO,devAiAb1771IrPlatinum,"AB-1771RTD-Platinum")
#device(ai,AB_IO,devAiAb1771IrCopper,"AB-1771RTD-Copper")
#device(ai,CAMAC_IO,devAiCamac,"Camac")
#device(ai,VME_IO,devAiAt5Vxi,"VXI-AT5-AI")
#device(ai,GPIB_IO,devAiK486Gpib,"Keithley-486")
#device(ai,VME_IO,devAiKscV215,"KSC-V215")
#device(ai,INST_IO,devAiVXStats,"VX stats")
#device(aai,CAMAC_IO,devAaiCamac,"Camac")
device(ao,CONSTANT,devAoSoft,"Soft Channel")
device(ao,CONSTANT,devAoSoftRaw,"Raw Soft Channel")
#device(ao,VME_IO,devAoVmiVme4100,"VMIVME-4100")
#device(ao,CONSTANT,devAoTestAsyn,"Test Asyn")
#device(ao,AB_IO,devAoAb1771Ofe,"AB-1771OFE")
#device(ao,CAMAC_IO,devAoCamac,"Camac")
#device(ao,VME_IO,devAoAt5Vxi,"VXI-AT5-AO")
#device(ao,INST_IO,devAoVXStats,"VX stats")
device(bi,CONSTANT,devBiSoft,"Soft Channel")
device(bi,CONSTANT,devBiSoftRaw,"Raw Soft Channel")
#device(bi,VME_IO,devBiMpv910,"MPV-910")
#device(bi,VME_IO,devBiXVme210,"XVME-210")
#device(bi,CONSTANT,devBiTestAsyn,"Test Asyn")
#device(bi,AB_IO,devBiAb,"AB-Binary Input")
#device(bi,AB_IO,devBiAb16,"AB-16 bit BI")
#device(bi,AB_IO,devBiAb32,"AB-32 bit BI")
#device(bi,CAMAC_IO,devBiCamac,"Camac")
#device(bi,VME_IO,devBiAt5Vxi,"VXI-AT5-BI")
#device(bi,VME_IO,devBiXy240,"XYCOM-240")
#device(bi,VME_IO,devBiHpe1368a,"VXI-HPE1368-VS")
#device(bi,VME_IO,devBiAt8Fp,"AT8-FP10S")
#device(bi,VME_IO,devBiAvme9440,"AVME9440 I")
device(bo,CONSTANT,devBoSoft,"Soft Channel")
device(bo,CONSTANT,devBoSoftRaw,"Raw Soft Channel")
#device(bo,VME_IO,devBoMpv902,"MPV-902")
#device(bo,VME_IO,devBoXVme220,"XVME-220")
#device(bo,CONSTANT,devBoTestAsyn,"Test Asyn")
#device(bo,AB_IO,devBoAb,"AB-Binary Output")
#device(bo,AB_IO,devBoAb16,"AB-16 bit BO")
#device(bo,AB_IO,devBoAb32,"AB-32 bit BO")
#device(bo,CAMAC_IO,devBoCamac,"Camac")
#device(bo,VME_IO,devBoAt5Vxi,"VXI-AT5-BO")
#device(bo,GPIB_IO,devBoK486Gpib,"Keithley-486")
#device(bo,VME_IO,devBoXy240,"XYCOM-240")
#device(bo,VME_IO,devBoHpe1368a,"VXI-HPE1368-VS")
#device(bo,VME_IO,devBoAt8Fp,"AT8-FP10S")
#device(bo,VME_IO,devBoAvme9440,"AVME9440 O")
device(event,CONSTANT,devEventSoft,"Soft Channel")
#device(event,VME_IO,devEventMz8310,"Mizar-8310")
#device(event,CONSTANT,devEventTestIoEvent,"Test IoEvent")
#device(event,VME_IO,devErEpicsEvent,"APS event receiver")
#device(histogram,CONSTANT,devHistogramSoft,"Soft Channel")
#device(histogram,CONSTANT,devHistogramTestAsyn,"Test Asyn")
device(longin,CONSTANT,devLiSoft,"Soft Channel")
#device(longin,CAMAC_IO,devLiCamac,"Camac")
#device(longin,INST_IO,devLiVXStats,"VX stats")
device(longout,CONSTANT,devLoSoft,"Soft Channel")
#device(longout,CAMAC_IO,devLoCamac,"Camac")
device(mbbi,CONSTANT,devMbbiSoft,"Soft Channel")
device(mbbi,CONSTANT,devMbbiSoftRaw,"Raw Soft Channel")
#device(mbbi,VME_IO,devMbbiMpv910,"MPV-910")
#device(mbbi,VME_IO,devMbbiXVme210,"XVME-210")
#device(mbbi,CONSTANT,devMbbiTestAsyn,"Test Asyn")
#device(mbbi,AB_IO,devMbbiAb,"AB-Binary Input")
#device(mbbi,AB_IO,devMbbiAb16,"AB-16 bit BI")
#device(mbbi,AB_IO,devMbbiAb32,"AB-32 bit BI")
#device(mbbi,AB_IO,devMbbiAbAdapterStat,"AB-Adapter Status")
#device(mbbi,AB_IO,devMbbiAbCardStat,"AB-Card Status")
#device(mbbi,CAMAC_IO,devMbbiCamac,"Camac")
#device(mbbi,VME_IO,devMbbiAt5Vxi,"VXI-AT5-BI")
#device(mbbi,VME_IO,devMbbiXy240,"XYCOM-240")
#device(mbbi,VME_IO,devMbbiHpe1368a,"VXI-HPE1368-VS")
#device(mbbi,VME_IO,devMbbiAt8Fp,"AT8-FP10S")
#device(mbbi,VME_IO,devMbbiAvme9440,"AVME9440 I")
device(mbbiDirect,CONSTANT,devMbbiDirectSoft,"Soft Channel")
device(mbbiDirect,CONSTANT,devMbbiDirectSoftRaw,"Raw Soft Channel")
#device(mbbiDirect,VME_IO,devMbbiDirectMpv910,"MPV-910")
#device(mbbiDirect,VME_IO,devMbbiDirectXVme210,"XVME-210")
#device(mbbiDirect,AB_IO,devMbbiDirectAb,"AB-Binary Input")
#device(mbbiDirect,AB_IO,devMbbiDirectAb16,"AB-16 bit BI")
#device(mbbiDirect,AB_IO,devMbbiDirectAb32,"AB-32 bit BI")
#device(mbbiDirect,CAMAC_IO,devMbbiDirectCamac,"Camac")
#device(mbbiDirect,VME_IO,devMbbiDirectAt5Vxi,"VXI-AT5-BI")
device(mbbo,CONSTANT,devMbboSoft,"Soft Channel")
device(mbbo,CONSTANT,devMbboSoftRaw,"Raw Soft Channel")
#device(mbbo,VME_IO,devMbboMpv902,"MPV-902")
#device(mbbo,VME_IO,devMbboXVme220,"XVME-220")
#device(mbbo,CONSTANT,devMbboTestAsyn,"Test Asyn")
#device(mbbo,AB_IO,devMbboAb,"AB-Binary Output")
#device(mbbo,AB_IO,devMbboAb16,"AB-16 bit BO")
#device(mbbo,AB_IO,devMbboAb32,"AB-32 bit BO")
#device(mbbo,VME_IO,devMbboAt5Vxi,"VXI-AT5-BO")
#device(mbbo,GPIB_IO,devMbboK486Gpib,"Keithley-486")
#device(mbbo,VME_IO,devMbboXy240,"XYCOM-240")
#device(mbbo,VME_IO,devMbboHpe1368a,"VXI-HPE1368-VS")
#device(mbbo,VME_IO,devMbboAt8Fp,"AT8-FP10S")
#device(mbbo,VME_IO,devMbboAvme9440,"AVME9440 O")
device(mbboDirect,CONSTANT,devMbboDirectSoft,"Soft Channel")
device(mbboDirect,CONSTANT,devMbboDirectSoftRaw,"Raw Soft Channel")
#device(mbboDirect,VME_IO,devMbboDirectMpv902,"MPV-902")
#device(mbboDirect,VME_IO,devMbboDirectXVme220,"XVME-220")
#device(mbboDirect,AB_IO,devMbboDirectAb,"AB-Binary Output")
#device(mbboDirect,AB_IO,devMbboDirectAb16,"AB-16 bit BO")
#device(mbboDirect,AB_IO,devMbboDirectAb32,"AB-32 bit BO")
#device(mbboDirect,CAMAC_IO,devMbboDirectCamac,"Camac")
#device(mbboDirect,VME_IO,devMbboDirectAt5Vxi,"VXI-AT5-BO")
#device(pulseCounter,VME_IO,devPcMz8310,"Mizar-8310")
#device(pulseDelay,VME_IO,devPdMz8310,"Mizar-8310")
#device(pulseTrain,CONSTANT,devPtSoft,"Soft Channel")
#device(pulseTrain,VME_IO,devPtMz8310,"Mizar-8310")
#device(steppermotor,VME_IO,devSmCompumotor1830,"Compumotor 1830")
#device(steppermotor,VME_IO,devSmOms6Axis,"OMS 6-Axis")
#device(steppermotor,AB_IO,devSmAB1746Hstp1,"Allen Bradley 1746-HTSP1")
device(stringin,CONSTANT,devSiSoft,"Soft Channel")
#device(stringin,CONSTANT,devSiTestAsyn,"Test Asyn")
device(stringout,CONSTANT,devSoSoft,"Soft Channel")
#device(stringout,CONSTANT,devSoTestAsyn,"Test Asyn")
device(subArray,CONSTANT,devSASoft,"Soft Channel")
#device(timer,VME_IO,devTmMizar8310,"Mizar-8310")
#device(timer,VME_IO,devTmDg535,"DG 535")
#device(timer,VME_IO,devTmAt5Vxi,"VXI-AT5-TIME")
device(waveform,CONSTANT,devWfSoft,"Soft Channel")
#device(waveform,VME_IO,devWfXy566Sc,"XYCOM-566 Single Channel")
#device(waveform,VME_IO,devWfComet,"Comet Digitizer")
#device(waveform,VME_IO,devWfJoergerVtr1,"Joerger Digitizer")
#device(waveform,CONSTANT,devWfTestAsyn,"Test Asyn")
#device(waveform,VME_IO,devWfDvx2502,"DVX-2502")
#device(waveform,VME_IO,devWfPentek4261,"Pentek 4261")
#device(waveform,CAMAC_IO,devWfCamac,"Camac")
#device(waveform,VME_IO,devWfJoergerVtr1,"Joerger-VTR1")
#device(waveform,VME_IO,devWfComet,"Omnibyte-COMET")
#device(eg,VME_IO,devEg,"APS event generator G")
#device(egevent,VME_IO,devEgEvent,"APS event generator E")
#device(er,VME_IO,devEr,"APS event receiver")
#device(erevent,VME_IO,devErevent,"APS event receiver")
#device(wait,CONSTANT,devWaitIoEvent,"Soft Channel")
#device(ai,INST_IO,devAiCan,"CANbus")
#device(ao,INST_IO,devAoCan,"CANbus")
#device(bi,INST_IO,devBiCan,"CANbus")
#device(bo,INST_IO,devBoCan,"CANbus")
#device(mbbi,INST_IO,devMbbiCan,"CANbus")
#device(mbbo,INST_IO,devMbboCan,"CANbus")
#device(mbbiDirect,INST_IO,devMbbiDirectCan,"CANbus")
#device(mbboDirect,INST_IO,devMbboDirectCan,"CANbus")
#device(bi,VME_IO,devBiVmic2534,"Vmic2534")
#device(bo,VME_IO,devBoVmic2534,"Vmic2534")
#device(mbbi,VME_IO,devMbbiVmic2534,"Vmic2534")
#device(mbbo,VME_IO,devMbboVmic2534,"Vmic2534")
#include "symb.dbd"
#device(ai,AB_IO,devAiAbSlcDcm,"AB-SLC500DCM")
#device(ai,AB_IO,devAiAbSlcDcmSigned,"AB-SLC500DCM-Signed")
#device(ao,AB_IO,devAoAbSlcDcm,"AB-SLC500DCM")
#device(longin,AB_IO,devLiAbSlcDcm,"AB-SLC500DCM")
#device(longout,AB_IO,devLoAbSlcDcm,"AB-SLC500DCM")
#driver(drvXy010)
#driver(drvVxi)
#driver(drvGpib)
#driver(drvBitBus)
#driver(drvBb910)
#driver(drvXy210)
#driver(drvBb902)
#driver(drvXy220)
#driver(drvXy566)
#driver(drvDvx)
#driver(drvVmi4100)
#driver(drvAb)
#driver(drvAt5Vxi)
#driver(drvCompuSm)
#driver(drvOms)
#driver(drvMz8310)
#driver(drvHpe1368a)
#driver(drvXy240)
#driver(drvKscV215)
#driver(drvComet)
#driver(drvJgvtr1)
#driver(drvFp)
#driver(drvFpm)
#driver(drvIpac)
#driver(drvTip810)
#driver(drvVmi2534)
#include "bptTypeJdegC.dbd"
#include "bptTypeJdegF.dbd"
#include "bptTypeKdegC.dbd"
#include "bptTypeKdegF.dbd"

216
streamApp/base-3-13LIBOBJS Normal file
View File

@ -0,0 +1,216 @@
LIBOBJS += $(EPICS_BASE_BIN)/aaiRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/aaoRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/aiRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/aoRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/biRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/boRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/calcRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/calcoutRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/compressRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/dfanoutRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/egRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/egeventRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/erRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/ereventRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/eventRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/fanoutRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/gsubRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/histogramRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/longinRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/longoutRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/mbbiRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/mbbiDirectRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/mbboRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/mbboDirectRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/palRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/permissiveRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/pidRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/pulseCounterRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/pulseDelayRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/pulseTrainRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/scanRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/recWaitCa.o
#LIBOBJS += $(EPICS_BASE_BIN)/recDynLink.o
#LIBOBJS += $(EPICS_BASE_BIN)/recDynLinkTest.o
LIBOBJS += $(EPICS_BASE_BIN)/selRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/seqRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/stateRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/steppermotorRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/stringinRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/stringoutRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/subRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/subArrayRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/timerRecord.o
#LIBOBJS += $(EPICS_BASE_BIN)/waitRecord.o
LIBOBJS += $(EPICS_BASE_BIN)/waveformRecord.o
#
# Device Support
#
#LIBOBJS += $(EPICS_BASE_BIN)/devAaiCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiDvx2502.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiKscV215.o
LIBOBJS += $(EPICS_BASE_BIN)/devAiSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devAiSoftRaw.o
#LIBOBJS += $(EPICS_BASE_BIN)/devVXStats.o
LIBOBJS += $(EPICS_BASE_BIN)/devAiTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiXy566Di.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiXy566DiL.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiXy566Se.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAaoCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAoCamac.o
LIBOBJS += $(EPICS_BASE_BIN)/devAoSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devAoSoftRaw.o
LIBOBJS += $(EPICS_BASE_BIN)/devAoTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAoVmiVme4100.o
#LIBOBJS += $(EPICS_BASE_BIN)/devApsEg.o
#LIBOBJS += $(EPICS_BASE_BIN)/devApsEr.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAt5Vxi.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAt8Fp.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAvme9440.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBiCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBiMpv910.o
LIBOBJS += $(EPICS_BASE_BIN)/devBiSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devBiSoftRaw.o
LIBOBJS += $(EPICS_BASE_BIN)/devBiTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBiXVme210.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBoCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBoMpv902.o
LIBOBJS += $(EPICS_BASE_BIN)/devBoSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devBoSoftRaw.o
LIBOBJS += $(EPICS_BASE_BIN)/devBoTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBoXVme220.o
#LIBOBJS += $(EPICS_BASE_BIN)/devCommonGpib.o
LIBOBJS += $(EPICS_BASE_BIN)/devEventSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devEventTestIoEvent.o
LIBOBJS += $(EPICS_BASE_BIN)/devHistogramSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devHistogramTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devHpe1368a.o
#LIBOBJS += $(EPICS_BASE_BIN)/devLiCamac.o
LIBOBJS += $(EPICS_BASE_BIN)/devLiSoft.o
#LIBOBJS += $(EPICS_BASE_BIN)/devLoCamac.o
LIBOBJS += $(EPICS_BASE_BIN)/devLoSoft.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiDirectCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiDirectMpv910.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbbiDirectSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbbiDirectSoftRaw.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiDirectXVme210.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiMpv910.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbbiSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbbiSoftRaw.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbbiTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiXVme210.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboDirectCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboDirectMpv902.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbboDirectSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbboDirectSoftRaw.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboDirectXVme220.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboMpv902.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbboSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbboSoftRaw.o
LIBOBJS += $(EPICS_BASE_BIN)/devMbboTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboXVme220.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMz8310.o
#LIBOBJS += $(EPICS_BASE_BIN)/devPtSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devSASoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devSiSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devSiTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devSmCompumotor1830.o
#LIBOBJS += $(EPICS_BASE_BIN)/devSmOms6Axis.o
LIBOBJS += $(EPICS_BASE_BIN)/devSoSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devSoTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devTimerMz8310.o
#LIBOBJS += $(EPICS_BASE_BIN)/devWfCamac.o
#LIBOBJS += $(EPICS_BASE_BIN)/devWfComet.o
#LIBOBJS += $(EPICS_BASE_BIN)/devWfDvx2502.o
#LIBOBJS += $(EPICS_BASE_BIN)/devWfJoergerVtr1.o
LIBOBJS += $(EPICS_BASE_BIN)/devWfSoft.o
LIBOBJS += $(EPICS_BASE_BIN)/devWfTestAsyn.o
#LIBOBJS += $(EPICS_BASE_BIN)/devWfXy566Sc.o
#LIBOBJS += $(EPICS_BASE_BIN)/devWfPentek4261.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXy240.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAB1771IFE.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAB1771IL.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAB1771IR.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAB1771IXE.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAB1771OFE.o
#LIBOBJS += $(EPICS_BASE_BIN)/devABSLCDCM.o
#LIBOBJS += $(EPICS_BASE_BIN)/devABBINARY.o
#LIBOBJS += $(EPICS_BASE_BIN)/devABStatus.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAiCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devAoCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBiCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBoCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbbiDirectCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devMbboDirectCan.o
#LIBOBJS += $(EPICS_BASE_BIN)/devVmic2534.o
#LIBOBJS += $(EPICS_BASE_BIN)/symb
#
# Driver support ANSI
#
#LIBOBJS += $(EPICS_BASE_BIN)/drvAb.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvAt5Vxi.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvEpvxi.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvEpvxiMsg.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvHp1404a.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvHpe1368a.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvHpe1445a.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvKscV215.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvMz8310.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvStc.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvTime.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvCaenV265.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvVipc310.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvVipc610.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvIpMv162.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvIpac.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvTip810.o
#
# Driver support NON ANSI
#
#LIBOBJS += $(EPICS_BASE_BIN)/module_types.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvBB232.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvBb902.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvBb910.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvBitBus.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvComet.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvCompuSm.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvDvx.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvFp.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvFpm.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvGpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvJgvtr1.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvMsg.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvOms.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvTranServ.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvVmi4100.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvXy010.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvXy210.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvXy220.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvXy240.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvXy566.o
#LIBOBJS += $(EPICS_BASE_BIN)/drvVmic2534.o
#
#from src/devOpt
#
#LIBOBJS += $(EPICS_BASE_BIN)/devAnalytekGpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devBBInteract.o
#LIBOBJS += $(EPICS_BASE_BIN)/devGpibInteract.o
#LIBOBJS += $(EPICS_BASE_BIN)/devK486Gpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devLibOpt.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXxDc5009Gpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXxDg535Gpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXxK196Gpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXxK263Gpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXxSkeletonGpib.o
#LIBOBJS += $(EPICS_BASE_BIN)/devXxSr620Gpib.o

View File

@ -0,0 +1,21 @@
BIN="<library directory>"
DBD="<dbd directory>"
HOME="<ioc home direcory>"
#where can protocols be located?
STREAM_PROTOCOL_PATH=".:protocols:../protocols/"
cd BIN
ld < iocCore
ld < streamApp.munch
dbLoadDatabase "streamApp.dbd",DBD
drvAsynIPPortConfigure "terminal", "xxx.xxx.xxx.xxx:40000"
#load the records
cd HOME
dbLoadRecords "example.db","PREFIX=DZ"
#lots of debug output
#streamDebug=1
iocInit

38
streamApp/example.cmd Normal file
View File

@ -0,0 +1,38 @@
dbLoadDatabase "O.Common/streamApp.dbd"
streamApp_registerRecordDeviceDriver
#where can protocols be located?
epicsEnvSet "STREAM_PROTOCOL_PATH", ".:protocols:../protocols/"
#setup the busses
#example serial port setup
#drvAsynSerialPortConfigure "COM2", "/dev/ttyS1"
#asynOctetSetInputEos "COM2",0,"\r\n"
#asynOctetSetOutputEos "COM2",0,"\r\n"
#asynSetOption ("COM2", 0, "baud", "9600")
#asynSetOption ("COM2", 0, "bits", "8")
#asynSetOption ("COM2", 0, "parity", "none")
#asynSetOption ("COM2", 0, "stop", "1")
#asynSetOption ("COM2", 0, "clocal", "Y")
#asynSetOption ("COM2", 0, "crtscts", "N")
#example telnet style IP port setup
drvAsynIPPortConfigure "terminal", "localhost:40000"
asynOctetSetInputEos "terminal",0,"\r\n"
asynOctetSetOutputEos "terminal",0,"\r\n"
#example VXI11 (GPIB via IP) port setup
#vxi11Configure "GPIB","ins023",1,5.0,"hpib"
#load the records
dbLoadRecords "example.db","PREFIX=DZ"
#dbLoadRecords "scalcout.db","PREFIX=DZ"
#lots! of debug output
#var streamDebug 1
iocInit
#enable debug output
var streamDebug 1

170
streamApp/example.db Normal file
View File

@ -0,0 +1,170 @@
# process this record to reload all stream protocols
record (sub, "$(PREFIX):reload")
{
field (SNAM, "streamReload")
}
# some scaling -10...10V <-> 0x0000...0xffff and back
record (ao, "$(PREFIX):ao")
{
field (DESC, "An analog value")
field (DTYP, "stream")
field (OUT, "@example.proto set-ao terminal")
field (PREC, "3")
field (LINR, "LINEAR")
field (ESLO, "0.000305180437934") # 20.0 / 0xffff
field (EOFF, "-10")
field (DRVL, "-10")
field (DRVH, "10")
field (EGU, "V")
}
record (ai, "$(PREFIX):ai")
{
field (DESC, "An analog value")
field (DTYP, "stream")
field (INP, "@example.proto ai terminal")
field (PREC, "3")
field (LINR, "LINEAR")
field (ESLO, "0.000305180437934") # 20.0 / 0xffff
field (EOFF, "-10")
field (EGU, "V")
}
# simple integer and binary i/o
record (longout, "$(PREFIX):lo")
{
field (DESC, "An integer value")
field (DTYP, "stream")
field (OUT, "@example.proto lo terminal")
}
record (longin, "$(PREFIX):li")
{
field (DESC, "An integer value")
field (DTYP, "stream")
field (INP, "@example.proto li terminal")
}
record (bo, "$(PREFIX):bo")
{
field (DESC, "A bit value")
field (DTYP, "stream")
field (OUT, "@example.proto bo terminal")
field (MASK, "42")
field (ZNAM, "OFF")
field (ONAM, "ON")
}
record (bi, "$(PREFIX):bi")
{
field (DESC, "A bit value")
field (DTYP, "stream")
field (INP, "@example.proto bi terminal")
field (ZNAM, "OFF")
field (ONAM, "ON")
}
# playing with enums
record (mbbo, "$(PREFIX):mbbo")
{
field (DESC, "Print Enums")
field (DTYP, "stream")
field (OUT, "@example.proto enums terminal")
field (ZRST, "A")
field (ZRVL, "2")
field (ONST, "B")
field (ONVL, "3")
field (TWST, "C")
field (TWVL, "1")
field (THST, "D")
field (THVL, "0")
}
record (stringout, "$(PREFIX):command")
{
field (DTYP, "stream")
field (OUT, "@example.proto COMMAND terminal")
}
record (stringin, "$(PREFIX):info")
{
field (DTYP, "stream")
field (INP, "@example.proto info terminal")
}
# prints all available checksums
record (stringout, "$(PREFIX):checksum")
{
field (DTYP, "stream")
field (OUT, "@example.proto checksum terminal")
}
# this record gets any (terminated) input line
record (stringin, "$(PREFIX):spy")
{
field (DTYP, "stream")
field (INP, "@example.proto spy terminal")
field (SCAN, "I/O Intr")
field (FLNK, "$(PREFIX):log5")
}
# these records log the last few input lines
record (stringin, "$(PREFIX):log5")
{
field (INP, "$(PREFIX):log4")
field (FLNK, "$(PREFIX):log4")
}
record (stringin, "$(PREFIX):log4")
{
field (INP, "$(PREFIX):log3")
field (FLNK, "$(PREFIX):log3")
}
record (stringin, "$(PREFIX):log3")
{
field (INP, "$(PREFIX):log2")
field (FLNK, "$(PREFIX):log2")
}
record (stringin, "$(PREFIX):log2")
{
field (INP, "$(PREFIX):log1")
field (FLNK, "$(PREFIX):log1")
}
record (stringin, "$(PREFIX):log1")
{
field (INP, "$(PREFIX):spy")
}
# caput to A,B,C or PROC to process this
record (calcout, "$(PREFIX):calcout")
{
field (DTYP, "stream")
field (OUT, "@example.proto calcout terminal")
field (A, "3.1415")
field (B, "15")
field (C, "8")
field (CALC, "0") # should be a valid expression
field (DESC, "filename")
}
# read a long string as a waveform of characteres
record (waveform, "$(PREFIX):hugestring")
{
field (DTYP, "stream")
field (INP, "@example.proto char_wave_in terminal")
field (FTVL, "CHAR")
field (NELM, "1000")
}
# write an array of strings
record (waveform, "$(PREFIX):strings")
{
field (DTYP, "stream")
field (INP, "@example.proto string_wave_out terminal")
field (FTVL, "STRING")
field (NELM, "10")
}

127
streamApp/example.proto Normal file
View File

@ -0,0 +1,127 @@
# example stream protocol file
Terminator = CR LF;
ReplyTimeout = 10000; # 10 sec is very long, for keyboard input
ReadTimeout = 1000; # also long for keyboard input
binary {
out "%B\x00\xff";
}
# note the field access
ai {
out "%(NAME)s [int] ? ";
in "%i"; # read to RVAL and convert
}
set-ao {
out '%(NAME)s = %f %(EGU)s [0x%04x]';
}
li {
out "%(NAME)s [int] ? ";
in "%i";
}
lo {
out '%(NAME)s = %i = %#x = %b(bin) = %D(BCD)';
}
bi {
out "%(NAME)s [0 or 1] ? ";
in "%i";
}
# using variables
s0 = false;
s1 = true;
bo {
out '%(NAME)s = %i = %{\${s0}|\${s1}} = "%s"';
}
enums
{
out "%{choice0|choice1|choice2} %d %s";
}
checksum {
out "%s%<sum> sum";
out "%s%<nsum> nsum";
out "%s%<-sum> -sum";
out "%s%<notsum> notsum";
out "%s%<~sum> ~sum";
out "%s%<xor> xor";
out "%s%<crc8> crc8";
out "%s%<ccitt8> ccitt8";
out "%s%<sum16> sum16";
out "%s%<crc16> crc16";
out "%s%<crc16r> crc16r";
out "%s%<ccitt16> ccitt16";
out "%s%<ccitt16a> ccitt16 with augment";
out "%s%<sum32> sum32";
out "%s%<crc32> crc32";
out "%s%<crc32r> crcr32";
out "%s%<jamcrc> jamcrc";
out "%s%<adler32> adler32";
out "%s%0<sum> sum (ASCII)";
out "%s%0<nsum> nsum (ASCII)";
out "%s%0<-sum> -sum (ASCII)";
out "%s%0<notsum> notsum (ASCII)";
out "%s%0<~sum> ~sum (ASCII)";
out "%s%0<xor> xor (ASCII)";
out "%s%0<crc8> crc8 (ASCII)";
out "%s%0<ccitt8> ccitt8 (ASCII)";
out "%s%0<sum16> sum16 (ASCII)";
out "%s%0<crc16> crc16 (ASCII)";
out "%s%0<crc16r> crc16r (ASCII)";
out "%s%0<ccitt16> ccitt16 (ASCII)";
out "%s%0<ccitt16a> ccitt16 with augment (ASCII)";
out "%s%0<sum32> sum32 (ASCII)";
out "%s%0<crc32> crc32 (ASCII)";
out "%s%0<crc32r> crcr32 (ASCII)";
out "%s%0<jamcrc> jamcrc (ASCII)";
out "%s%0<adler32> adler32 (ASCII)";
out "%s%0<hexsum8> hexsum8 (ASCII)";
}
command {
out "%s";
}
info {
out "%s";
in "%39c";
}
read {
in "%39c";
}
spy {
extraInput=ignore;
PollPeriod = 10;
in "%39c";
}
# accessing fields
calcout {
out "OVAL=%f A=%(A)f B=%(B)f C=%(C)f";
}
scalcout {
out "OVAL=%f SOV=%s A=%(A)f B=%(B)f AA=%(AA)s";
}
# output an array of strings
string_wave_out {
separator = ", ";
out "waveform %(NAME)s = (%s)";
}
char_wave_in {
outterminator = "";
out CR LF "Enter String: ";
in "%1000c";
out 'Got: "%s"' CR LF;
}

34
streamApp/regexp.README Normal file
View File

@ -0,0 +1,34 @@
How to use regular expressions in StreamDevice.
First, you need the PCRE library.
If it is already installed for your (Linux) system (try: rpm -ql pcre),
set the following variables in your RELEASE file:
PCRE_INCLUDE=<direcrory of pcre.h>
PCRE_LIB=<direcrory of libpcre.so>
For vxWorks, Windows and others you're probably out of luck here.
In that case, download the PCRE package from www.pcre.org and
epics.web.psi.ch/software/streamdevice/pcre/Makefile and compile
PCRE as an EPICS application. Use the variable PCRE in your RELEASE file
to define the location of this application.
If either PCRE or PCRE_INCLUDE or PCRE_LIB are set in the RELEASE file,
StreamDevice is automatically build with regular expression support.
The syntax is %/regexp/. It can only be used in input. It returns the
next string that matches the regexp. Anything before this string is skipped.
To use sub-expressions use %.n/rexexp/ where n is a number from 1 to 9
to match the n-th sub-expression.
It is possible to limit the input length to the match algorithm like
%m/regexp/ where m is the maximal length.
Example:
in "%100.1/<title>(.*)<\/title>/";
This searches the next 100 bytes and returns the string bewteen
<title> and </title>. Any input before <title> is skipped. Any input
after </title> is left in the buffer (and can by matched by other formats).
Note that the / in </title> must be escaped.
See regexp.cmd, regexp.proto, regexp.db for a working example.

10
streamApp/regexp.cmd Normal file
View File

@ -0,0 +1,10 @@
dbLoadDatabase "O.Common/streamApp.dbd"
streamApp_registerRecordDeviceDriver
# no autoconnect for web servers (see regexp.proto)
drvAsynIPPortConfigure web epics.web.psi.ch:80 0 1
dbLoadRecords regexp.db
iocInit
# var streamDebug 1

5
streamApp/regexp.db Normal file
View File

@ -0,0 +1,5 @@
record (stringin, "DZ:regexp")
{
field (DTYP, "stream")
field (INP, "@regexp.proto readTitle web")
}

18
streamApp/regexp.proto Normal file
View File

@ -0,0 +1,18 @@
# regular expression example
# extract the title of from a web page
outterminator = NL;
interminator = "</html>" NL; # terminators can have arbitrary length
# Web servers close the connection after sending a page.
# Thus, we can't use autoconnect (see drvAsynIPPortConfigure)
# Handle connection manually in protocol.
readTitle {
extraInput=ignore;
connect 1000; # connect to server, 1 second timeout
out "GET http://epics.web.psi.ch/"; # HTTP request
in "%.1/<title>(.*)<\/title>/"; # get string in <title></title>
disconnect; # servers closes, so do we.
}

19
streamApp/simple.cmd Normal file
View File

@ -0,0 +1,19 @@
dbLoadDatabase "O.Common/streamApp.dbd"
streamApp_registerRecordDeviceDriver
#where can protocols be located?
epicsEnvSet "STREAM_PROTOCOL_PATH", ".:protocols:../protocols/"
#setup the busses
#drvAsynIPPortConfigure "L0", "localhost:40000"
vxi11Configure "L0","gpib-dz-1",0,0.0,"gpib0",0,0
#load the records
dbLoadRecords "simple.db","P=DZ,BUS=L0 28"
var streamDebug 1
iocInit
#enable debug output
var streamDebug 1

15
streamApp/simple.db Normal file
View File

@ -0,0 +1,15 @@
record (stringout, "$(P):cmd")
{
field (DTYP, "stream")
field (OUT, "@simple.proto cmd $(BUS)")
}
record (stringout, "$(P):info")
{
field (DTYP, "stream")
field (OUT, "@simple.proto info $(BUS)")
}
record (stringin, "$(P):read")
{
field (DTYP, "stream")
field (INP, "@simple.proto read $(BUS)")
}

13
streamApp/simple.proto Normal file
View File

@ -0,0 +1,13 @@
terminator = CR LF;
cmd {
out "%s";
}
info {
extrainput=ignore;
out "%s";
in "%39c";
}
read {
in "%39c";
}

View File

@ -0,0 +1,3 @@
include "base-3-13.dbd"
include "asyn.dbd"
include "stream.dbd"

View File

@ -0,0 +1,37 @@
/***************************************************************
* StreamDevice Support *
* *
* (C) 2005 Dirk Zimoch (dirk.zimoch@psi.ch) *
* *
* This is an example application initializer for StreamDevice. *
* Please refer to the HTML files in ../doc/ for a detailed *
* documentation. *
* *
* If you do any changes in this file, you are not allowed to *
* redistribute it any more. If there is a bug or a missing *
* feature, send me an email and/or your patch. If I accept *
* your changes, they will go to the next release. *
* *
* DISCLAIMER: If this software breaks something or harms *
* someone, it's your problem. *
* *
***************************************************************/
#include <epicsThread.h>
#include <iocsh.h>
#include <devStream.h>
int main(int argc,char *argv[])
{
#ifdef DEBUGFILE
#define STR2(x) #x
#define STR(x) STR2(x)
StreamDebugFile = fopen(STR(DEBUGFILE), "w");
#endif
if(argc>=2) {
iocsh(argv[1]);
epicsThreadSleep(.2);
}
iocsh(NULL);
return(0);
}

155
streamApp/terminal.tcl Executable file
View File

@ -0,0 +1,155 @@
#!/usr/bin/env wish
wm iconify .
proc createTerm {sock} {
global socket port
toplevel .$sock
text .$sock.t -yscrollcommand ".$sock.v set"
scrollbar .$sock.v -command ".$sock.t yview"
.$sock.t tag configure output -foreground red
.$sock.t tag configure input -foreground darkgreen
grid rowconfigure .$sock 0 -weight 1
grid columnconfigure .$sock 0 -weight 1
grid .$sock.t .$sock.v -sticky nsew
bind .$sock.t <Destroy> "close $sock; unset socket(.$sock.t)"
bind .$sock.t <F1> "%W delete 0.1 end"
set socket(.$sock.t) $sock
focus .$sock.t
wm title .$sock "port $port <-> [fconfigure $sock -peername]"
}
set port [lindex $argv 0]
if {$port == ""} { set port 40000 }
if [catch {
socket -server connect $port
} msg ] {
return -code error "$msg (port $port)"
}
proc connect {sock addr port} {
fconfigure $sock -blocking 0 -buffering none
createTerm $sock
fileevent $sock readable "receiveHandler $sock"
}
proc sendReply {sock text} {
.$sock.t mark set insert end
.$sock.t insert end $text
.$sock.t see end
puts -nonewline $sock $text
}
proc checkNum {n} {
if {[string is integer $n] && $n >= 0} {return $n}
return -code error "argument $n must be a positive number"
}
proc receiveHandler {sock} {
set a [read $sock]
if [eof $sock] {
destroy .$sock
return
}
.$sock.t mark set insert end
.$sock.t insert end $a output
.$sock.t see end
set l [split $a]
if [catch {
switch -- [lindex $l 0] {
"disconnect" {
sendReply $sock [string range $a 11 end]
destroy .$sock
}
"echo" {
sendReply $sock [string range $a 5 end]
}
"longmsg" {
set length [checkNum [lindex $l 1]]
sendReply $sock "[string range x[string repeat 0123456789abcdefghijklmnopqrstuvwxyz [expr $length / 36 + 1]] 1 $length]\n"
}
"wait" {
set wait [checkNum [lindex $l 1]]
after $wait [list sendReply $sock "Done\n"]
}
"start" {
set wait [checkNum [lindex $l 1]]
set ::counter 0
after $wait sendAsync $wait [list [lindex $l 2]]
sendReply $sock "Started\n"
}
"stop" {
set ::counter -1
sendReply $sock "Stopped\n"
}
"set" {
set ::values([lindex $a 1]) [lrange $l 2 end-1]
sendReply $sock "Ok\n"
}
"get" {
if [info exists ::values([lindex $l 1])] {
sendReply $sock "[lindex $l 1] $::values([lindex $l 1])\n"
} else {
sendReply $sock "ERROR: [lindex $l 1] not found\n"
}
}
"help" {
sendReply $sock "help this text\n"
sendReply $sock "echo string reply string\n"
sendReply $sock "wait msec reply Done after some time\n"
sendReply $sock "start msec start sending messages priodically\n"
sendReply $sock "stop stop sending messages\n"
sendReply $sock "set key value set a value\n"
sendReply $sock "get key reply value\n"
sendReply $sock "disconnect close connection\n"
}
}
} msg] {
sendReply $sock "ERROR: $msg\n"
puts stderr $::errorInfo
}
}
proc sendAsync {wait message} {
if {$::counter < 0} return
foreach term [array names ::socket] {
sendReply $::socket($term) "Message number [incr ::counter] $message\n";
}
after $wait sendAsync $wait [list $message]
}
if {[info proc tkTextInsert] != ""} {
set insert tkTextInsert
set paste tkTextPaste
} else {
set insert tk::TextInsert
set paste tk_textPaste
}
rename $insert tkTextInsert_org
rename $paste tkTextPaste_org
proc $insert {w s} {
global socket
if {[string equal $s ""] || [string equal [$w cget -state] "disabled"]} {
return
}
sendReply $socket($w) $s
}
proc $paste {w x y} {
global insert
set s [selection get -displayof $w]
$insert $w $s
}
#remove bindings on Control-<letter>
for {set ascii 0x61} {$ascii <= 0x7a} {incr ascii} {
bind Text <Control-[format %c $ascii]> ""
}
#remove bindings on symbolic tags
foreach tag {Clear Paste Copy Cut} {
bind Text <<$tag>> ""
}
bind Text <Control-Key> [list $insert %W %A]

900
streamApp/test.adl Normal file
View File

@ -0,0 +1,900 @@
file {
name="/afs/psi.ch/user/z/zimoch/top/StreamDevice-2/streamApp/test.adl"
version=030100
}
display {
object {
x=261
y=341
width=552
height=362
}
clr=14
bclr=50
cmap=""
gridSpacing=5
gridOn=1
snapToGrid=1
}
"color map" {
ncolors=65
colors {
ffffff,
ececec,
dadada,
c8c8c8,
bbbbbb,
aeaeae,
9e9e9e,
919191,
858585,
787878,
696969,
5a5a5a,
464646,
2d2d2d,
000000,
00d800,
1ebb00,
339900,
2d7f00,
216c00,
fd0000,
de1309,
be190b,
a01207,
820400,
5893ff,
597ee1,
4b6ec7,
3a5eab,
27548d,
fbf34a,
f9da3c,
eeb62b,
e19015,
cd6100,
ffb0ff,
d67fe2,
ae4ebc,
8b1a96,
610a75,
a4aaff,
8793e2,
6a73c1,
4d52a4,
343386,
c7bb6d,
b79d5c,
a47e3c,
7d5627,
58340f,
99ffff,
73dfff,
4ea5f9,
2a63e4,
0a00b8,
ebf1b5,
d4db9d,
bbc187,
a6a462,
8b8239,
73ff6b,
52da3b,
3cb420,
289315,
1a7309,
}
}
"text update" {
object {
x=50
y=105
width=390
height=10
}
monitor {
chan="$(P):log9"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=115
width=390
height=10
}
monitor {
chan="$(P):log8"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=125
width=390
height=10
}
monitor {
chan="$(P):log7"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=135
width=390
height=10
}
monitor {
chan="$(P):log6"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=145
width=390
height=10
}
monitor {
chan="$(P):log5"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=155
width=390
height=10
}
monitor {
chan="$(P):log4"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=165
width=390
height=10
}
monitor {
chan="$(P):log3"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=175
width=390
height=10
}
monitor {
chan="$(P):log2"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=185
width=390
height=10
}
monitor {
chan="$(P):log1"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=195
width=390
height=10
}
monitor {
chan="$(P):log0"
clr=14
bclr=4
}
limits {
}
}
"text entry" {
object {
x=50
y=265
width=390
height=20
}
control {
chan="$(P):cmd"
clr=14
bclr=12
}
clrmod="alarm"
limits {
}
}
"text update" {
object {
x=50
y=215
width=390
height=14
}
monitor {
chan="$(P):spy"
clr=14
bclr=12
}
clrmod="alarm"
limits {
}
}
text {
object {
x=5
y=105
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log9"
}
text {
object {
x=5
y=115
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log8"
}
text {
object {
x=5
y=125
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log7"
}
text {
object {
x=5
y=135
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log6"
}
text {
object {
x=5
y=145
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log5"
}
text {
object {
x=5
y=155
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log4"
}
text {
object {
x=5
y=165
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log3"
}
text {
object {
x=5
y=175
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log2"
}
text {
object {
x=5
y=185
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log1"
}
text {
object {
x=5
y=195
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log0"
}
text {
object {
x=5
y=215
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="spy"
}
text {
object {
x=5
y=270
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="cmd"
}
text {
object {
x=5
y=295
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="info"
}
"text entry" {
object {
x=50
y=290
width=390
height=20
}
control {
chan="$(P):info"
clr=14
bclr=12
}
clrmod="alarm"
limits {
}
}
"text update" {
object {
x=50
y=235
width=390
height=14
}
monitor {
chan="$(P):spybin"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
text {
object {
x=5
y=235
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="spybin"
}
text {
object {
x=5
y=320
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="request"
}
"text entry" {
object {
x=50
y=315
width=390
height=20
}
control {
chan="$(P):request"
clr=14
bclr=12
}
clrmod="alarm"
limits {
}
}
"text update" {
object {
x=50
y=340
width=390
height=14
}
monitor {
chan="$(P):reply"
clr=14
bclr=12
}
clrmod="alarm"
limits {
}
}
text {
object {
x=5
y=340
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="reply"
}
"text update" {
object {
x=445
y=340
width=100
height=15
}
monitor {
chan="$(P):reply.STAT"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
"text update" {
object {
x=445
y=315
width=100
height=15
}
monitor {
chan="$(P):request.STAT"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
"text update" {
object {
x=445
y=290
width=100
height=15
}
monitor {
chan="$(P):info.STAT"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
"text update" {
object {
x=445
y=265
width=100
height=15
}
monitor {
chan="$(P):cmd.STAT"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
"text update" {
object {
x=445
y=235
width=100
height=15
}
monitor {
chan="$(P):spybin.STAT"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
"text update" {
object {
x=445
y=215
width=100
height=15
}
monitor {
chan="$(P):spy.STAT"
clr=14
bclr=12
}
clrmod="alarm"
format="string"
limits {
}
}
"text update" {
object {
x=50
y=5
width=390
height=10
}
monitor {
chan="$(P):log19"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=15
width=390
height=10
}
monitor {
chan="$(P):log18"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=25
width=390
height=10
}
monitor {
chan="$(P):log17"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=35
width=390
height=10
}
monitor {
chan="$(P):log16"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=45
width=390
height=10
}
monitor {
chan="$(P):log15"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=55
width=390
height=10
}
monitor {
chan="$(P):log14"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=65
width=390
height=10
}
monitor {
chan="$(P):log13"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=75
width=390
height=10
}
monitor {
chan="$(P):log12"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=85
width=390
height=10
}
monitor {
chan="$(P):log11"
clr=14
bclr=4
}
limits {
}
}
"text update" {
object {
x=50
y=95
width=390
height=10
}
monitor {
chan="$(P):log10"
clr=14
bclr=4
}
limits {
}
}
text {
object {
x=5
y=5
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log19"
}
text {
object {
x=5
y=15
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log18"
}
text {
object {
x=5
y=25
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log17"
}
text {
object {
x=5
y=35
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log16"
}
text {
object {
x=5
y=45
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log15"
}
text {
object {
x=5
y=55
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log14"
}
text {
object {
x=5
y=65
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log13"
}
text {
object {
x=5
y=75
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log12"
}
text {
object {
x=5
y=85
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log11"
}
text {
object {
x=5
y=95
width=25
height=10
}
"basic attribute" {
clr=14
}
textix="log10"
}

10
streamApp/test.cmd Normal file
View File

@ -0,0 +1,10 @@
dbLoadDatabase "O.Common/streamApp.dbd"
streamApp_registerRecordDeviceDriver
epicsEnvSet "STREAM_PROTOCOL_PATH", "."
drvAsynIPPortConfigure "terminal", "localhost:40000"
dbLoadRecords "test.db","P=TEST"
iocInit
var streamDebug 1

133
streamApp/test.db Normal file
View File

@ -0,0 +1,133 @@
record (stringout, "$(P):cmd")
{
field (DTYP, "stream")
field (OUT, "@test.proto command terminal")
field (VAL, "")
}
record (stringout, "$(P):info")
{
field (DTYP, "stream")
field (OUT, "@test.proto info terminal")
}
record (stringout, "$(P):request")
{
field (DTYP, "stream")
field (OUT, "@test.proto request($(P):reply.VAL) terminal")
}
record (stringin, "$(P):reply")
{
}
record (stringin, "$(P):spy")
{
field (DTYP, "stream")
field (INP, "@test.proto spy terminal")
field (SCAN, "I/O Intr")
field (FLNK, "$(P):log19")
}
record (stringin, "$(P):log0")
{
field (INP, "$(P):spy")
}
record (stringin, "$(P):log1")
{
field (INP, "$(P):log0")
field (FLNK, "$(P):log0")
}
record (stringin, "$(P):log2")
{
field (INP, "$(P):log1")
field (FLNK, "$(P):log1")
}
record (stringin, "$(P):log3")
{
field (INP, "$(P):log2")
field (FLNK, "$(P):log2")
}
record (stringin, "$(P):log4")
{
field (INP, "$(P):log3")
field (FLNK, "$(P):log3")
}
record (stringin, "$(P):log5")
{
field (INP, "$(P):log4")
field (FLNK, "$(P):log4")
}
record (stringin, "$(P):log6")
{
field (INP, "$(P):log5")
field (FLNK, "$(P):log5")
}
record (stringin, "$(P):log7")
{
field (INP, "$(P):log6")
field (FLNK, "$(P):log6")
}
record (stringin, "$(P):log8")
{
field (INP, "$(P):log7")
field (FLNK, "$(P):log7")
}
record (stringin, "$(P):log9")
{
field (INP, "$(P):log8")
field (FLNK, "$(P):log8")
}
record (stringin, "$(P):log10")
{
field (INP, "$(P):log9")
field (FLNK, "$(P):log9")
}
record (stringin, "$(P):log11")
{
field (INP, "$(P):log10")
field (FLNK, "$(P):log10")
}
record (stringin, "$(P):log12")
{
field (INP, "$(P):log11")
field (FLNK, "$(P):log11")
}
record (stringin, "$(P):log13")
{
field (INP, "$(P):log12")
field (FLNK, "$(P):log12")
}
record (stringin, "$(P):log14")
{
field (INP, "$(P):log13")
field (FLNK, "$(P):log13")
}
record (stringin, "$(P):log15")
{
field (INP, "$(P):log14")
field (FLNK, "$(P):log14")
}
record (stringin, "$(P):log16")
{
field (INP, "$(P):log15")
field (FLNK, "$(P):log15")
}
record (stringin, "$(P):log17")
{
field (INP, "$(P):log16")
field (FLNK, "$(P):log16")
}
record (stringin, "$(P):log18")
{
field (INP, "$(P):log17")
field (FLNK, "$(P):log17")
}
record (stringin, "$(P):log19")
{
field (INP, "$(P):log18")
field (FLNK, "$(P):log18")
}
record (waveform, "$(P):spybin")
{
field (DTYP, "stream")
field (INP, "@test.proto spybin terminal")
field (FTVL, "CHAR")
field (NELM, "2000")
field (SCAN, "I/O Intr")
}

25
streamApp/test.proto Normal file
View File

@ -0,0 +1,25 @@
terminator = CR LF;
readtimeout = 1000;
pollperiod = 10;
replytimeout = 1000;
command {
out "%s";
}
info {
out "%s";
in "%39c";
}
request {
out "%s";
in "%(\$1)39c";
}
spy {
extraInput=ignore;
in "%39c";
}
spybin {
readtimeout = 1;
terminator = "";
extraInput=ignore;
in "%r";
}

21
streamApp/test.readme Normal file
View File

@ -0,0 +1,21 @@
Simple test environment:
1) Start device simulation:
terminal.tcl &
Or set up a real device.
2) Start ioc:
xterm -e test.cmd &
Or edit test.cmd first.
3) Start medm:
medm -x -macro P=TEST test.adl &
Records:
TEST:cmd - writes string to device
TEST:info - writes string and reads reply (result in same record)
TEST:spy - gets any input line from device
TEST:spybin - gets any input (binary waveform)
TEST:log* - history of TEST:spy
Try to write 'help' to TEST:cmd.

40
streamApp/tests/printdouble Executable file
View File

@ -0,0 +1,40 @@
#!/bin/bash
filename=$$
trap "rm -f $filename.c $filename " EXIT TERM KILL
cat > $filename.c << EOF
#line 8
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** args)
{
union {
float f;
double d;
unsigned char c [8];
} u;
int i,j;
for (i = 1; i < argc; i++)
{
u.f = atof (args[i]);
for (j = 0; j < 4; j++)
{
printf ("\\\\x%02x", u.c[j]);
}
printf ("\n");
u.d = atof (args[i]);
for (j = 0; j < 8; j++)
{
printf ("\\\\x%02x", u.c[j]);
}
printf ("\n");
}
return 0;
}
EOF
cc -Wall -pedantic $filename.c -o $filename && $filename "$@"

View File

@ -0,0 +1,180 @@
#
# Usage
# 1) source this file
# 2) define variables records, protocol, starup
# 3) call startioc
# 4) use ioccmd, assure, receive, send,...
# 5) call finish
set testname [file tail $argv0]
proc bgerror msg {
error $::errorInfo
}
set debug 0
proc debugmsg {string} {
global debug
if $debug {puts $string}
}
proc deviceconnect {s addr port} {
debugmsg "incoming connenction"
global sock
set sock $s
fconfigure $sock -blocking no -buffering none -translation binary
fileevent $sock readable "receiveHandler $sock"
}
set inputbuffer {}
proc receiveHandler {sock} {
global inputbuffer inputlog
set input [read $sock]
puts -nonewline $inputlog $input
append inputbuffer $input
debugmsg "receiving \"[escape $inputbuffer]\""
if [eof $sock] {
close $sock
debugmsg "connection closed by ioc"
return
}
}
proc startioc {} {
global debug records protocol startup port sock ioc testname env
set fd [open test.db w]
puts $fd $records
close $fd
set fd [open test.proto w]
puts $fd $protocol
close $fd
set fd [open test.cmd w 0777]
puts $fd "#!../O.$env(EPICS_HOST_ARCH)/streamApp"
puts $fd "dbLoadDatabase ../O.Common/streamApp.dbd"
puts $fd "streamApp_registerRecordDeviceDriver"
puts $fd "epicsEnvSet STREAM_PROTOCOL_PATH ."
puts $fd "drvAsynIPPortConfigure device localhost:$port"
puts $fd "dbLoadRecords test.db"
puts $fd $startup
puts $fd "iocInit"
puts $fd "dbl"
puts $fd "dbior stream 2"
puts $fd "var streamDebug 1"
close $fd
set ioc [open "|../O.$env(EPICS_HOST_ARCH)/streamApp test.cmd >& $testname.ioclog 2>@stderr" w]
fconfigure $ioc -blocking yes -buffering none
debugmsg "waiting to connect"
vwait sock
}
set lastcommand ""
set line 0
proc ioccmd {command} {
global ioc
global lastcommand
global line
set lastcommand $command
set line 0
debugmsg "$command"
puts $ioc $command
}
proc send {string} {
global sock
debugmsg "sending \"[escape $string]\""
puts -nonewline $sock $string
}
set timeout 5000
proc receive {} {
global inputbuffer timeoutid timeout
set timeoutid [after $timeout {
set inputbuffer {}
}]
if {$inputbuffer == {}} { vwait inputbuffer }
after cancel $timeoutid
if {$inputbuffer == {}} {
return -code error "Error in receive: timeout"
}
set index [string first "\n" $inputbuffer]
if {$index > -1} {
set input [string range $inputbuffer 0 $index]
set inputbuffer [string range $inputbuffer [expr $index+1] end]
} else {
set input $inputbuffer
set inputbuffer {}
}
return $input
}
set faults 0
proc assure {args} {
global faults
global lastcommand
global line
incr line
set input {}
for {set i 0} {$i < [llength $args]} {incr i} {
if [catch {lappend input [receive]} msg] {
puts stderr $msg
break
}
}
set notfound {}
foreach expected $args {
set index [lsearch -exact $input $expected]
if {$index > -1} {
set input [lreplace $input $index $index]
} else {
lappend notfound $expected
}
}
if {[llength $notfound] || [llength $input]} {
puts stderr "In command \"$lastcommand\""
}
foreach string $notfound {
puts stderr "Error in assure: line $line missing \"[escape $string]\""
}
foreach string $input {
puts stderr "Error in assure: got unexpected \"[escape $string]\""
}
if {[llength $notfound] || [llength $input]} {incr faults}
}
proc escape {string} {
while {![string is print -failindex index $string]} {
set char [string index $string $index]
scan $char "%c" code
switch $char {
"\r" { set escaped "\\r" }
"\n" { set escaped "\\n" }
"\a" { set escaped "\\a" }
"\t" { set escaped "\\t" }
default { set escaped [format "<%02x>" $code] }
}
set string [string replace $string $index $index $escaped]
}
return $string
}
proc finish {} {
global ioc timeout testname faults
set timeout 1000
while {![catch {set string [receive]}]} {
puts stderr "Error in finish: unexpected \"[escape $string]\""
incr faults
}
after 100
close $ioc
if $faults {
puts "Test failed."
exit 1
}
puts "Test passed."
eval file delete [glob -nocomplain test.*] StreamDebug.log $testname.ioclog
}
set port 40123
socket -server deviceconnect $port
set inputlog [open "test.inputlog" w]

94
streamApp/tests/test64Bit Executable file
View File

@ -0,0 +1,94 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:ao")
{
field (DTYP, "stream")
field (OUT, "@test.proto ao device")
}
record (longout, "DZ:longout")
{
field (DTYP, "stream")
field (OUT, "@test.proto longout device")
}
record (bo, "DZ:bo")
{
field (DTYP, "stream")
field (OUT, "@test.proto bo device")
field (MASK, "-1")
}
record (mbbo, "DZ:mbbo")
{
field (DTYP, "stream")
field (OUT, "@test.proto mbbo device")
field (ZRVL, "0")
field (ONVL, "-1")
}
record (mbboDirect, "DZ:mbboDirect")
{
field (DTYP, "stream")
field (OUT, "@test.proto mbboDirect device")
}
record (ai, "DZ:ai")
{
field (DTYP, "stream")
field (INP, "@test.proto ai device")
}
record (longin, "DZ:longin")
{
field (DTYP, "stream")
field (INP, "@test.proto longin device")
}
}
set protocol {
Terminator = LF;
# these records use signed values: %d
ao {out "ao %.3f %d %(VAL).3f %(RVAL)d";}
longout {out "longout %d %(VAL)d";}
ai {out "ai?"; in "%d"; out "ai %d";}
longin {out "longin?"; in "%d"; out "longin %d";}
# these records use unsigned values: %u, %x
bo {out "bo %u %x %b";}
mbbo {out "mbbo %u %x %b";}
mbboDirect {out "mbboDirect %u %x %b";}
bi {out "bi?"; in "%d"; out "bi %d %x";}
mbbi {out "mbbi?"; in "%d"; out "mbbi %d %x";}
mbbiDirect {out "mbbiDirect?"; in "%d"; out "mbbiDirect %d %x";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:ao -1}
assure "ao -1.000 -1 -1.000 -1\n"
ioccmd {dbpf DZ:longout -1}
assure "longout -1 -1\n"
ioccmd {dbpf DZ:bo 1}
assure "bo 4294967295 ffffffff 11111111111111111111111111111111\n"
ioccmd {dbpf DZ:mbbo 1}
assure "mbbo 4294967295 ffffffff 11111111111111111111111111111111\n"
ioccmd {dbpf DZ:mbboDirect.B0 1}
assure "mbboDirect 1 1 1\n"
ioccmd {dbpf DZ:mbboDirect -1}
assure "mbboDirect 65535 ffff 1111111111111111\n"
ioccmd {dbpf DZ:ai.PROC 1}
assure "ai?\n"
send "-1\n"
assure "ai -1\n"
ioccmd {dbpf DZ:longin.PROC 1}
assure "longin?\n"
send "-1\n"
assure "longin -1\n"
finish

35
streamApp/tests/testBo Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (bo, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
field (ZNAM, "OFF")
field (ONAM, "ON")
}
}
set protocol {
test1 {out "%i %r %s";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 0}
assure "0 \x00 OFF"
ioccmd {dbpf DZ:test1 1}
assure "1 \x01 ON"
finish

30
streamApp/tests/testChecksum Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
}
set protocol {
test1 {out 0x55 0x40 0x04 0x00 0x00 'z;' "%<sum>";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 "1"}
assure "\x55\x40\x04\x00\x00z;\x4e"
finish

43
streamApp/tests/testCompare Executable file
View File

@ -0,0 +1,43 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
}
set protocol {
Terminator = LF;
@mismatch { out "mismatch"; }
test1 {out "set %.2f"; in "ack %=.2f X"; out "OK"; }
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 3.14}
assure "set 3.14\n"
send "ack 3.14 X\n"
assure "OK\n"
ioccmd {dbpf DZ:test1 0}
assure "set 0.00\n"
send "ack 0.00 X\n"
assure "OK\n"
ioccmd {dbpf DZ:test1 1}
assure "set 1.00\n"
send "ack 1.0 X\n"
assure "mismatch\n"
finish

View File

@ -0,0 +1,56 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (longin, "DZ:test1")
{
field (DTYP, "stream")
field (INP, "@test.proto integer device")
}
record (ai, "DZ:test2")
{
field (DTYP, "stream")
field (INP, "@test.proto double device")
}
}
set protocol {
Terminator = LF;
integer {out "integer"; in "n: %?d xx"; out "n = %d"; }
double {out "double"; in "n: %?g xx"; out "n = %.4f"; }
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1.PROC 1}
assure "integer\n";
send "n: -12 xx\n";
assure "n = -12\n";
ioccmd {dbpf DZ:test1.PROC 1}
assure "integer\n";
send "n: xx\n";
assure "n = 0\n";
ioccmd {dbpf DZ:test2.PROC 1}
assure "double\n";
send "n: 3.1415 xx\n";
assure "n = 3.1415\n";
ioccmd {dbpf DZ:test2.PROC 1}
assure "double\n";
send "n: xx\n";
assure "n = 0.0000\n";
finish

107
streamApp/tests/testEnum Executable file
View File

@ -0,0 +1,107 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (longout, "DZ:testout")
{
field (DTYP, "stream")
field (OUT, "@test.proto out device")
}
record (longin, "DZ:testin")
{
field (DTYP, "stream")
field (INP, "@test.proto in device")
}
record (longout, "DZ:testout1")
{
field (DTYP, "stream")
field (OUT, "@test.proto out1 device")
}
record (longin, "DZ:testin1")
{
field (DTYP, "stream")
field (INP, "@test.proto in1 device")
}
record (longout, "DZ:testout2")
{
field (DTYP, "stream")
field (OUT, "@test.proto out2 device")
}
record (longin, "DZ:testin2")
{
field (DTYP, "stream")
field (INP, "@test.proto in2 device")
}
}
set protocol {
Terminator = LF;
out {out "%{zero|one|two}bla";}
in {in "%{zero|one|two}bla"; out "%d";}
out1 {out "%#{zero|one|two}bla";}
in1 {in "%#{zero|one|two}bla"; out "%d";}
out2 {out "%#{zero=-1|one|two=5}bla";}
in2 {in "%#{zero=-1|one|two=5}bla"; out "%d";}
}
set startup {
var streamDebug 1
}
set debug 0
startioc
ioccmd {dbpf DZ:testout 0}
assure "zerobla\n"
ioccmd {dbpf DZ:testout 1}
assure "onebla\n"
ioccmd {dbpf DZ:testout 2}
assure "twobla\n"
ioccmd {dbpf DZ:testout1 0}
assure "zerobla\n"
ioccmd {dbpf DZ:testout1 1}
assure "onebla\n"
ioccmd {dbpf DZ:testout1 2}
assure "twobla\n"
ioccmd {dbpf DZ:testout2 -1}
assure "zerobla\n"
ioccmd {dbpf DZ:testout2 0}
assure "onebla\n"
ioccmd {dbpf DZ:testout2 5}
assure "twobla\n"
ioccmd {dbpf DZ:testin.PROC 1}
send "zerobla\n"
assure "0\n"
ioccmd {dbpf DZ:testin.PROC 1}
send "onebla\n"
assure "1\n"
ioccmd {dbpf DZ:testin.PROC 1}
send "twobla\n"
assure "2\n"
ioccmd {dbpf DZ:testin1.PROC 1}
send "zerobla\n"
assure "0\n"
ioccmd {dbpf DZ:testin1.PROC 1}
send "onebla\n"
assure "1\n"
ioccmd {dbpf DZ:testin1.PROC 1}
send "twobla\n"
assure "2\n"
ioccmd {dbpf DZ:testin2.PROC 1}
send "zerobla\n"
assure "-1\n"
ioccmd {dbpf DZ:testin2.PROC 1}
send "onebla\n"
assure "0\n"
ioccmd {dbpf DZ:testin2.PROC 1}
send "twobla\n"
assure "5\n"
finish

67
streamApp/tests/testFormatm Executable file
View File

@ -0,0 +1,67 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:ao")
{
field (DTYP, "stream")
field (OUT, "@test.proto ao device")
}
record (ai, "DZ:ai")
{
field (DTYP, "stream")
field (INP, "@test.proto ai device")
}
}
set protocol {
Terminator = LF;
ao {out "'%m' '%.4m' '%+.4m' '% .4m' '% +.4m' '%10.4m' '%-10.4m'";}
ai {out "?"; in "%m"; out "%.4e";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:ao 0}
assure "'000000+00' '0000+00' '+0000+00' ' 0000+00' '+0000+00' ' 0000+00' '0000+00 '\n"
ioccmd {dbpf DZ:ao 1}
assure "'100000-05' '1000-03' '+1000-03' ' 1000-03' '+1000-03' ' 1000-03' '1000-03 '\n"
ioccmd {dbpf DZ:ao 1000}
assure "'100000-02' '1000+00' '+1000+00' ' 1000+00' '+1000+00' ' 1000+00' '1000+00 '\n"
ioccmd {dbpf DZ:ao 1000000}
assure "'100000+01' '1000+03' '+1000+03' ' 1000+03' '+1000+03' ' 1000+03' '1000+03 '\n"
ioccmd {dbpf DZ:ao -1}
assure "'-100000-05' '-1000-03' '-1000-03' '-1000-03' '-1000-03' ' -1000-03' '-1000-03 '\n"
ioccmd {dbpf DZ:ao 12345}
assure "'123450-01' '1235+01' '+1235+01' ' 1235+01' '+1235+01' ' 1235+01' '1235+01 '\n"
ioccmd {dbpf DZ:ao -1.2345e-15}
assure "'-123450-20' '-1235-18' '-1235-18' '-1235-18' '-1235-18' ' -1235-18' '-1235-18 '\n"
ioccmd {dbpf DZ:ao 1e-100}
assure "'100000-105' '1000-103' '+1000-103' ' 1000-103' '+1000-103' ' 1000-103' '1000-103 '\n"
ioccmd {dbpf DZ:ai.PROC 1}
assure "?\n"
send "+1234+56\n"
assure "1.2340e+59\n"
ioccmd {dbpf DZ:ai.PROC 1}
assure "?\n"
send "-1234-56\n"
assure "-1.2340e-53\n"
ioccmd {dbpf DZ:ai.PROC 1}
assure "?\n"
send "-12340000-60\n"
assure "-1.2340e-53\n"
ioccmd {dbpf DZ:ai.PROC 1}
assure "?\n"
send "+00000000+0\n"
assure "0.0000e+00\n"
finish

102
streamApp/tests/testFormats Executable file
View File

@ -0,0 +1,102 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:ao")
{
field (DTYP, "stream")
field (OUT, "@test.proto ao device")
field (EOFF, "-10")
field (ESLO, "0.000305180437934")
field (LINR, "LINEAR")
}
record (longout, "DZ:lo")
{
field (DTYP, "stream")
field (OUT, "@test.proto lo device")
}
record (longout, "DZ:bcd")
{
field (DTYP, "stream")
field (OUT, "@test.proto bcd device")
}
record (stringout, "DZ:chksum")
{
field (DTYP, "stream")
field (OUT, "@test.proto chksum device")
}
}
set protocol {
Terminator = LF;
ao {out "%.2f %.2e %.2E %.2g %.2G %i %d %u %o %04x %#.2f %#.2e %#.2E %#.2g %#.2G %#i %#d %#u %#o %#06x";}
lo {out "%d %(VAL)d %06d %x %06X %b %06b %.6b %B.! %06B.!";}
bcd {out "%D %6D %.2D %.4D %.6D %.8D %#D %#6D %#.2D %#.4D %#.6D";}
chksum {out "%s%<xor>";
out "%s%0<sum>";
out "%s%0<crc8>";
out "%s%0<crc16>";
out "%s%0<crc32>";
out "%s%0<adler32>";
}
}
set startup {
}
set debug 0
startioc
# Some formats give different results on 32 bit and 64 bit machines.
# This occurs when printing negative numbers with unsigned formats.
# This is normal. E.g. -1 HAS a different number of 1 bits.
# Specify the width field in the format if this is a problem.
ioccmd {dbpf DZ:ao 0}
assure "0.00 0.00e+00 0.00E+00 0 0 32767 32767 32767 77777 7fff 0.00 0.00e+00 0.00E+00 0.0 0.0 32767 32767 32767 077777 0x7fff\n"
ioccmd {dbpf DZ:ao 10}
assure "10.00 1.00e+01 1.00E+01 10 10 65535 65535 65535 177777 ffff 10.00 1.00e+01 1.00E+01 10. 10. 65535 65535 65535 0177777 0xffff\n"
ioccmd {dbpf DZ:ao -10}
assure "-10.00 -1.00e+01 -1.00E+01 -10 -10 0 0 0 0 0000 -10.00 -1.00e+01 -1.00E+01 -10. -10. 0 0 0 0 000000\n"
ioccmd {dbpf DZ:ao 1e-6}
assure "0.00 1.00e-06 1.00E-06 1e-06 1E-06 32768 32768 32768 100000 8000 0.00 1.00e-06 1.00E-06 1.0e-06 1.0E-06 32768 32768 32768 0100000 0x8000\n"
ioccmd {dbpf DZ:lo 0}
assure "0 0 000000 0 000000 0 000000 000000 . ......\n"
ioccmd {dbpf DZ:lo 12345}
assure "12345 12345 012345 3039 003039 11000000111001 11000000111001 111001 !!......!!!..! !!......!!!..!\n"
ioccmd {dbpf DZ:lo -1}
if {$tcl_platform(machine) == "x86_64"} {
assure "-1 -1 -00001 ffffffffffffffff FFFFFFFFFFFFFFFF 1111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
} else {
assure "-1 -1 -00001 ffffffff FFFFFFFF 11111111111111111111111111111111 11111111111111111111111111111111 111111 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
}
ioccmd {dbpf DZ:lo -1234}
if {$tcl_platform(machine) == "x86_64"} {
assure "-1234 -1234 -01234 fffffffffffffb2e FFFFFFFFFFFFFB2E 1111111111111111111111111111111111111111111111111111101100101110 1111111111111111111111111111111111111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
} else {
assure "-1234 -1234 -01234 fffffb2e FFFFFB2E 11111111111111111111101100101110 11111111111111111111101100101110 101110 !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!. !!!!!!!!!!!!!!!!!!!!!.!!..!.!!!.\n"
}
ioccmd {dbpf DZ:lo 255}
assure "255 255 000255 ff 0000FF 11111111 11111111 111111 !!!!!!!! !!!!!!!!\n"
ioccmd {dbpf DZ:lo 65535}
assure "65535 65535 065535 ffff 00FFFF 1111111111111111 1111111111111111 111111 !!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!\n"
ioccmd {dbpf DZ:bcd 1020304}
if {$tcl_platform(machine) == "x86_64"} {
assure "\0\0\0\0\1\2\3\4 \0\0\0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1\0\0\0\0 \4\3\2\1\0\0\0\0 \4 \4\3 \4\3\2\n"
} else {
assure "\1\2\3\4 \0\0\1\2\3\4 \4 \3\4 \2\3\4 \1\2\3\4 \4\3\2\1 \4\3\2\1\0\0 \4 \4\3 \4\3\2\n"
}
ioccmd {dbpf DZ:chksum "123456789"}
assure "1234567891\n"
assure "123456789DD\n"
assure "123456789F4\n"
assure "123456789FEE8\n"
assure "123456789FC891918\n"
assure "123456789091E01DE\n"
finish

View File

@ -0,0 +1,44 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (stringin, "DZ:test1")
{
field (DTYP, "stream")
field (INP, "@test.proto test1 device")
}
}
set protocol {
Terminator = CR LF;
test1 {out "Give input"; in "%s"; out "%s"; }
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1.PROC 1}
assure "Give input\r\n"
send "abc\r\n"
assure "abc\r\n"
ioccmd {dbpf DZ:test1.PROC 1}
assure "Give input\r\n"
send "x\r\n"
assure "x\r\n"
ioccmd {dbpf DZ:test1.PROC 1}
assure "Give input\r\n"
send "\r\n"
assure "\r\n"
finish

View File

@ -0,0 +1,45 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (stringin, "DZ:test1")
{
field (DTYP, "stream")
field (INP, "@test.proto test1 device")
}
}
set protocol {
InTerminator = CR CR CR;
OutTerminator = LF;
test1 {out "Give input"; in "%39c"; out "%s"; }
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1.PROC 1}
assure "Give input\n"
send "abc\r\r\r"
assure "abc\n"
ioccmd {dbpf DZ:test1.PROC 1}
assure "Give input\n"
send "klm\rxyz\r\r\r"
assure "klm\rxyz\n"
ioccmd {dbpf DZ:test1.PROC 1}
assure "Give input\n"
send "123\r\rxyz\r\r\r"
assure "123\r\rxyz\n"
finish

View File

@ -0,0 +1,73 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (bo, "DZ:ready")
{
field (DTYP, "stream")
field (OUT, "@test.proto ready device")
field (PINI, "YES")
}
record (stringin, "DZ:read")
{
field (DTYP, "stream")
field (INP, "@test.proto readintr device")
field (SCAN, "I/O Intr")
field (FLNK, "DZ:count")
}
record (calc, "DZ:count")
{
field (INPA, "DZ:count")
field (CALC, "A+1")
}
record (longout, "DZ:countout")
{
field (DTYP, "stream")
field (DOL, "DZ:count")
field (OMSL, "closed_loop")
field (OUT, "@test.proto printnum device")
}
record (stringout, "DZ:stringout")
{
field (DTYP, "stream")
field (DOL, "DZ:read")
field (OMSL, "closed_loop")
field (OUT, "@test.proto printstr device")
}
}
set protocol {
Terminator = LF;
ready {out "ready"; }
readintr {extraInput=ignore; in "%39c"; }
printnum {out "%d";}
printstr {out "%s";}
}
set startup {
var streamDebug 1
}
set debug 0
set rep 500
startioc
assure "ready\n"
after 1000
for {set i 1} {$i <= $rep} {incr i} {
append output "This is line $i.\n"
}
send $output
after 2000
ioccmd {dbpf "DZ:stringout.PROC" 1}
assure "This is line $rep.\n"
ioccmd {dbpf "DZ:countout.PROC" 1}
assure "$rep\n"
finish

View File

@ -0,0 +1,40 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (stringout, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
record (stringout, "DZ:test2")
{
field (DTYP, "stream")
field (OUT, "@test.proto test2 device")
}
}
set protocol {
test1 {out "%s";}
Terminator = "S" CR LF;
test2 { out "%s";}
}
set startup {
asynOctetSetOutputEos device -1 "A\n"
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 "string 1"}
assure "string 1A\n"
ioccmd {dbpf DZ:test2 "string 2"}
assure "string 2S\r\n"
finish

57
streamApp/tests/testPINI Executable file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
foreach rtype {ao bo mbbo mbboDirect longout stringout calcout} {
append records "
record ($rtype, \"DZ:$rtype\")
{
field (DTYP, \"stream\")
field (OUT, \"@test.proto init($rtype) device\")
field (PINI, \"YES\")
field (VAL, \"0\")
}
"
}
foreach rtype {ai bi mbbi mbbiDirect longin stringin waveform} {
append records "
record ($rtype, \"DZ:$rtype\")
{
field (DTYP, \"stream\")
field (INP, \"@test.proto init($rtype) device\")
field (PINI, \"YES\")
}
"
}
set protocol {
Terminator = LF;
init {out "init \$1"; }
}
set startup {
}
set debug 0
startioc
assure "init ao\n" \
"init bo\n" \
"init mbbo\n" \
"init mbboDirect\n" \
"init longout\n" \
"init stringout\n" \
"init ai\n" \
"init bi\n" \
"init mbbi\n" \
"init mbbiDirect\n" \
"init longin\n" \
"init stringin\n" \
"init calcout\n" \
"init waveform\n" \
finish

197
streamApp/tests/testRaw Executable file
View File

@ -0,0 +1,197 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (longout, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
}
set protocol {
Terminator = LF;
test1 {
out "%r"; out "%.1r"; out "%.2r"; out "%.3r"; out "%.4r"; out "%.5r";
out "%#r"; out "%#.1r"; out "%#.2r"; out "%#.3r"; out "%#.4r"; out "%#.5r";
out "%r"; out "%1r"; out "%2r"; out "%3r"; out "%4r"; out "%5r";
out "%0r"; out "%01r"; out "%02r"; out "%03r"; out "%04r"; out "%05r";
out "%#0r"; out "%#01r"; out "%#02r"; out "%#03r"; out "%#04r"; out "%#05r";
};
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 0}
assure "\x00\n"
assure "\x00\n"
assure "\x00\x00\n"
assure "\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\n"
assure "\x00\n"
assure "\x00\n"
assure "\x00\x00\n"
assure "\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\n"
assure "\x00\n"
assure "\x00\n"
assure "\x00\x00\n"
assure "\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\n"
assure "\x00\n"
assure "\x00\n"
assure "\x00\x00\n"
assure "\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\n"
assure "\x00\n"
assure "\x00\n"
assure "\x00\x00\n"
assure "\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\n"
ioccmd {dbpf DZ:test1 1}
assure "\x01\n"
assure "\x01\n"
assure "\x00\x01\n"
assure "\x00\x00\x01\n"
assure "\x00\x00\x00\x01\n"
assure "\x00\x00\x00\x00\x01\n"
assure "\x01\n"
assure "\x01\n"
assure "\x01\x00\n"
assure "\x01\x00\x00\n"
assure "\x01\x00\x00\x00\n"
assure "\x01\x00\x00\x00\x00\n"
assure "\x01\n"
assure "\x01\n"
assure "\x00\x01\n"
assure "\x00\x00\x01\n"
assure "\x00\x00\x00\x01\n"
assure "\x00\x00\x00\x00\x01\n"
assure "\x01\n"
assure "\x01\n"
assure "\x00\x01\n"
assure "\x00\x00\x01\n"
assure "\x00\x00\x00\x01\n"
assure "\x00\x00\x00\x00\x01\n"
assure "\x01\n"
assure "\x01\n"
assure "\x01\x00\n"
assure "\x01\x00\x00\n"
assure "\x01\x00\x00\x00\n"
assure "\x01\x00\x00\x00\x00\n"
ioccmd {dbpf DZ:test1 -1}
assure "\xff\n"
assure "\xff\n"
assure "\xff\xff\n"
assure "\xff\xff\xff\n"
assure "\xff\xff\xff\xff\n"
assure "\xff\xff\xff\xff\xff\n"
assure "\xff\n"
assure "\xff\n"
assure "\xff\xff\n"
assure "\xff\xff\xff\n"
assure "\xff\xff\xff\xff\n"
assure "\xff\xff\xff\xff\xff\n"
assure "\xff\n"
assure "\xff\n"
assure "\xff\xff\n"
assure "\xff\xff\xff\n"
assure "\xff\xff\xff\xff\n"
assure "\xff\xff\xff\xff\xff\n"
assure "\xff\n"
assure "\xff\n"
assure "\x00\xff\n"
assure "\x00\x00\xff\n"
assure "\x00\x00\x00\xff\n"
assure "\x00\x00\x00\x00\xff\n"
assure "\xff\n"
assure "\xff\n"
assure "\xff\x00\n"
assure "\xff\x00\x00\n"
assure "\xff\x00\x00\x00\n"
assure "\xff\x00\x00\x00\x00\n"
ioccmd {dbpf DZ:test1 269554195}
assure "\x13\n"
assure "\x13\n"
assure "\x12\x13\n"
assure "\x11\x12\x13\n"
assure "\x10\x11\x12\x13\n"
assure "\x00\x10\x11\x12\x13\n"
assure "\x13\n"
assure "\x13\n"
assure "\x13\x12\n"
assure "\x13\x12\x11\n"
assure "\x13\x12\x11\x10\n"
assure "\x13\x12\x11\x10\x00\n"
assure "\x13\n"
assure "\x13\n"
assure "\x00\x13\n"
assure "\x00\x00\x13\n"
assure "\x00\x00\x00\x13\n"
assure "\x00\x00\x00\x00\x13\n"
assure "\x13\n"
assure "\x13\n"
assure "\x00\x13\n"
assure "\x00\x00\x13\n"
assure "\x00\x00\x00\x13\n"
assure "\x00\x00\x00\x00\x13\n"
assure "\x13\n"
assure "\x13\n"
assure "\x13\x00\n"
assure "\x13\x00\x00\n"
assure "\x13\x00\x00\x00\n"
assure "\x13\x00\x00\x00\x00\n"
ioccmd {dbpf DZ:test1 -559038737}
assure "\xef\n"
assure "\xef\n"
assure "\xbe\xef\n"
assure "\xad\xbe\xef\n"
assure "\xde\xad\xbe\xef\n"
assure "\xff\xde\xad\xbe\xef\n"
assure "\xef\n"
assure "\xef\n"
assure "\xef\xbe\n"
assure "\xef\xbe\xad\n"
assure "\xef\xbe\xad\xde\n"
assure "\xef\xbe\xad\xde\xff\n"
assure "\xef\n"
assure "\xef\n"
assure "\xff\xef\n"
assure "\xff\xff\xef\n"
assure "\xff\xff\xff\xef\n"
assure "\xff\xff\xff\xff\xef\n"
assure "\xef\n"
assure "\xef\n"
assure "\x00\xef\n"
assure "\x00\x00\xef\n"
assure "\x00\x00\x00\xef\n"
assure "\x00\x00\x00\x00\xef\n"
assure "\xef\n"
assure "\xef\n"
assure "\xef\x00\n"
assure "\xef\x00\x00\n"
assure "\xef\x00\x00\x00\n"
assure "\xef\x00\x00\x00\x00\n"
finish

61
streamApp/tests/testRawFloat Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
}
set protocol {
Terminator = LF;
test1 {out "%R"; out "%#R"; out "%4R"; out "%#4R"; out "%8R"; out "%#8R";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 "0"}
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\x00\x00\x00\n"
ioccmd {dbpf DZ:test1 "1"}
assure "\x3f\x80\x00\x00\n"
assure "\x00\x00\x80\x3f\n"
assure "\x3f\x80\x00\x00\n"
assure "\x00\x00\x80\x3f\n"
assure "\x3f\xf0\x00\x00\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\x00\xf0\x3f\n"
ioccmd {dbpf DZ:test1 "-1"}
assure "\xbf\x80\x00\x00\n"
assure "\x00\x00\x80\xbf\n"
assure "\xbf\x80\x00\x00\n"
assure "\x00\x00\x80\xbf\n"
assure "\xbf\xf0\x00\x00\x00\x00\x00\x00\n"
assure "\x00\x00\x00\x00\x00\x00\xf0\xbf\n"
ioccmd {dbpf DZ:test1 "3.1415"}
assure "\x40\x49\x0e\x56\n"
assure "\x56\x0e\x49\x40\n"
assure "\x40\x49\x0e\x56\n"
assure "\x56\x0e\x49\x40\n"
assure "\x40\x09\x21\xca\xc0\x83\x12\x6f\n"
assure "\x6f\x12\x83\xc0\xca\x21\x09\x40\n"
finish

View File

@ -0,0 +1,76 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (stringin, "DZ:readTimeout")
{
field (DTYP, "stream")
field (INP, "@test.proto read device")
}
record (bo, "DZ:echo")
{
field (DTYP, "stream")
field (OUT, "@test.proto print(DZ:readTimeout) device")
}
}
set protocol {
Terminator = LF;
read {out "Give me input"; in "%s";}
print {out "Text:'%(\$1.VAL)s' SEVR=%(\$1.SEVR)d STAT=%(\$1.STAT)d";}
}
set startup {
}
set debug 0
startioc
# reply timeout
ioccmd {dbpf DZ:readTimeout.PROC 1}
assure "Give me input\n"
after 1100
ioccmd {dbpf DZ:echo.PROC 1}
ioccmd {dbpr DZ:echo 1}
assure "Text:'' SEVR=3 STAT=10\n"
# read timeout
ioccmd {dbpf DZ:readTimeout.PROC 1}
assure "Give me input\n"
send "Trulala"
after 200
ioccmd {dbpf DZ:echo.PROC 1}
assure "Text:'Trulala' SEVR=3 STAT=1\n"
# reply timeout again, old input stays
ioccmd {dbpf DZ:readTimeout.PROC 1}
assure "Give me input\n"
after 1100
ioccmd {dbpf DZ:echo.PROC 1}
assure "Text:'Trulala' SEVR=3 STAT=10\n"
# mismatch, partially parsed
ioccmd {dbpf DZ:readTimeout.PROC 1}
assure "Give me input\n"
send "bla extra\n"
after 200
ioccmd {dbpf DZ:echo.PROC 1}
assure "Text:'bla' SEVR=3 STAT=12\n"
# success
ioccmd {dbpf DZ:readTimeout.PROC 1}
assure "Give me input\n"
send "Input\n"
after 200
ioccmd {dbpf DZ:echo.PROC 1}
assure "Text:'Input' SEVR=0 STAT=0\n"
finish

View File

@ -0,0 +1,32 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (stringout, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
}
set protocol {
Terminator = LF;
test1 {out "%s";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 "string 1"}
assure "string 1\n"
finish

View File

@ -0,0 +1,81 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (stringin, "DZ:request")
{
field (DTYP, "stream")
field (INP, "@test.proto read device")
}
record (stringout, "DZ:echo")
{
field (DTYP, "stream")
field (DOL, "DZ:request")
field (OMSL, "closed_loop")
field (OUT, "@test.proto printstr device")
}
record (stringin, "DZ:spy")
{
field (DTYP, "stream")
field (INP, "@test.proto readintr device")
field (SCAN, "I/O Intr")
field (FLNK, "DZ:count")
}
record (calc, "DZ:count")
{
field (INPA, "DZ:count")
field (CALC, "A+1")
}
record (longout, "DZ:countout")
{
field (DTYP, "stream")
field (DOL, "DZ:count")
field (OMSL, "closed_loop")
field (OUT, "@test.proto printnum device")
}
record (stringout, "DZ:stringout")
{
field (DTYP, "stream")
field (DOL, "DZ:spy")
field (OMSL, "closed_loop")
field (OUT, "@test.proto printstr device")
}
}
set protocol {
Terminator = LF;
read {extraInput=ignore; InTerminator = ""; out "Give input"; in "%/.*253.*/"; }
readintr {extraInput=ignore; in "%39c"; }
printnum {out "%d";}
printstr {out "%s";}
}
set startup {
var streamDebug 1
}
set debug 0
set rep 500
startioc
ioccmd {dbpf "DZ:request.PROC" 1}
assure "Give input\n"
for {set i 1} {$i <= $rep} {incr i} {
append output "This is line $i.\n"
}
send $output
after 2000
ioccmd {dbpf "DZ:echo.PROC" 1}
assure "This is line 253.\n"
ioccmd {dbpf "DZ:stringout.PROC" 1}
assure "This is line $rep.\n"
ioccmd {dbpf "DZ:countout.PROC" 1}
assure "$rep\n"
finish

View File

@ -0,0 +1,59 @@
rm -f test.*
cat > test.cc << EOF
#include <StreamBuffer.h>
#include <assert.h>
#include <stdio.h>
int main () {
StreamBuffer haystack = "12345abc123xyz123";
StreamBuffer needle = "1n4m6p7q";
needle.remove(2,4);
assert (needle.equals("1n7q"));
needle.append("2x3y");
assert (needle.equals("1n7q2x3y"));
needle.remove(4);
assert (needle.equals("2x3y"));
needle.remove(1,1);
assert (needle.equals("23y"));
needle.truncate(-1);
assert (needle.equals("23"));
assert (haystack.find(needle) == 1);
assert (haystack.find(needle, 2) == 9);
assert (haystack.find(needle, -5) == 15);
assert (haystack.find("23", -5) == 15);
assert (haystack.find((char*)NULL, 10) == 10);
assert (haystack.find(needle, -1) == -1);
assert (haystack.find(needle, 100) == -1);
assert (haystack.find(needle, 0) == 1);
assert (haystack.find(needle, -100) == 1);
haystack.set("12345xy67890xy");
needle.set("xy");
assert (haystack.find(needle) == 5);
needle.set("x");
assert (haystack.find(needle) == 5);
haystack.set("12345\n67890\n");
needle.set("\n");
assert (haystack.find(needle) == 5);
haystack.set("12341234567890\n");
needle.set("2345");
assert (haystack.find(needle) == 5);
needle="7890";
assert (haystack.find(needle) == 10);
needle.append('\0');
assert (haystack.find(needle) == -1);
haystack.clear();
assert (haystack.find(needle) == -1);
haystack.set("deadbeef");
needle.clear();
assert (haystack.find(needle) == 0);
haystack.clear();
assert (haystack.find(needle) == 0);
return 0;
}
EOF
g++ -I ../../src ../../src/O.$EPICS_HOST_ARCH/StreamBuffer.o test.cc -o test.exe
test.exe || exit 1
rm test.*
echo "Test passed."

58
streamApp/tests/testTimestamp Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (ao, "DZ:test1")
{
field (DTYP, "stream")
field (OUT, "@test.proto test1 device")
}
record (ai, "DZ:test2")
{
field (DTYP, "stream")
field (INP, "@test.proto test2 device")
}
record (ai, "DZ:test3")
{
field (DTYP, "stream")
field (INP, "@test.proto test3 device")
}
}
set protocol {
Terminator = LF;
test1 {out "%T(%d.%m.%Y %H:%M:%.2S %z)"; }
test2 {out "?"; in "%T"; out "%.0f %T"; }
test3 {out "?"; in "%(TIME)T(%Ed. %B %Y %H:%M:%.S%+0100) %f"; out "%(TIME)T %f"; }
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:test1 1044068706.789}
assure "01.02.2003 04:05:06.79 +0100\n"
ioccmd {dbpf DZ:test2.PROC 1}
assure "?\n"
send "2003-02-01 04:05:06 +0100\n"
assure "1044068706 2003-02-01 04:05:06 +0100\n";
ioccmd {dbpf DZ:test3.PROC 1}
assure "?\n"
send "1. Feb 2003 04:05:06.789 3.1415\n"
assure "2003-02-01 04:05:06 +0100 3.141500\n";
package require Epics
array set PV [pvinfo DZ:test3.TSE]
if {$PV(VAL) != -2 || $PV(TIME) != "02/01/03 04:05:06.789000000"} {incr faults}
finish

56
streamApp/tests/testWaage Executable file
View File

@ -0,0 +1,56 @@
#!/usr/bin/env tclsh
source streamtestlib.tcl
# Define records, protocol and startup (text goes to files)
# The asynPort "device" is connected to a network TCP socket
# Talk to the socket with send/receive/assure
# Send commands to the ioc shell with ioccmd
set records {
record (bi, "DZ:sign")
{
field (DTYP, "stream")
field (INP, "@test.proto m(DZ:weight.A) device")
}
record (calc, "DZ:weight")
{
field (INPB, "DZ:sign")
field (CALC, "B?A:-A")
field (FLNK, "DZ:out")
}
record (ao, "DZ:out")
{
field (DTYP, "stream")
field (DOL, "DZ:weight")
field (OMSL, "closed_loop")
field (OUT, "@test.proto out device")
}
}
set protocol {
Terminator = LF;
m {out "w"; in "%*/ */%{-|}%(\$1)f Kg";}
out {out "%.2f";}
}
set startup {
}
set debug 0
startioc
ioccmd {dbpf DZ:sign.PROC 1}
assure "w\n"
send " - 15.20 Kg\n"
assure "-15.20\n"
ioccmd {dbpf DZ:sign.PROC 1}
assure "w\n"
send " 15.00 Kg\n"
assure "15.00\n"
finish

18
streamApp/tests/testall Executable file
View File

@ -0,0 +1,18 @@
for i in test*
do
if [ $i != testall -a -x $i ]
then
echo $i
if ! $i
then
echo "Failed."
(( fail++ ))
fi
fi
done
if [ "$fail" ]
then echo "$fail tests failed"
else echo "All tests passsed."
fi
exit $fail