Files
epics-base/src/tools/makeBaseApp.pl
1997-07-17 19:28:37 +00:00

1135 lines
29 KiB
Perl
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/local/bin/perl
#
# Author: Kay-Uwe Kasemir,
# based on Marty Kraimer's makeBaseApp
#
# 1-27-97
#
# Notes:
# 1) The perl location /usr/local/bin/perl may be wrong,
# the safest way to run this script is via a direct
# perl <script>
# 2) You need Perl 5.x to run this.
# Get it from http://www.perl.com if you don't have it, yet.
# These extensions come with the basic perl distribution
# and ran on sun4 and WIN32:
use Cwd;
use Getopt::Std;
use File::Copy;
$startdir=cwd();
# remove auto-mount path which confuses directory name comparison
$startdir=~s'^/tmp_mnt'';
Cleanup (1, "Shouldn't run in Home Directory") if (GetHome() eq $startdir);
# look for options
getopt("b");
if ($opt_e)
{
$example=1;
}
$user=GetUser();
@apps=@ARGV;
# if this script was called with full path to base,
# extract EPICS/base.
# (this failes for '/base/' starting at root but that's unlikely)
if ($0 =~ m'(/.*/base)/bin/')
{
$epics_base = $1;
}
else
{
$epics_base=$opt_b if ($opt_b);
}
Cleanup (1,"Cannot find EPICS base, use full path or '-b'") unless $epics_base;
unless (-f 'Makefile')
{
open OUT, ">Makefile" or die "Cannot open Makefile";
print OUT "#Makefile generated by makeBaseApp.pl\n";
print OUT "TOP = .\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "DIRS += \$(wildcard *App)\n";
print OUT "DIRS += iocBoot\n";
print OUT "include \$(TOP)/config/RULES_TOP\n";
close OUT;
}
unless (-d 'config')
{
mkdir 'config', 0777;
chdir 'config' or die "Cannot create config directory";
open OUT, ">CONFIG" or die "Cannot create CONFIG";
print OUT '#CONFIG',"\n";
print OUT '# Add any changes to make rules here',"\n";
print OUT '#CROSS_COMPILER_TARGET_ARCHS = mv167',"\n";
close OUT;
open OUT, ">CONFIG_APP" or die "Cannot create CONFIG_APP";
print OUT '#CONFIG_APP ',"\n";
print OUT 'include $(TOP)/config/RELEASE',"\n";
print OUT 'ifndef T_A',"\n";
print OUT 'T_A = $(HOST_ARCH)',"\n";
print OUT 'endif',"\n";
print OUT 'include $(EPICS_BASE)/config/CONFIG',"\n";
print OUT ' ',"\n";
print OUT '#Other share areas can be added similar to following',"\n";
print OUT '#ifdef <share_top>',"\n";
print OUT '#USR_INCLUDES += -I$(<share_top>)/include',"\n";
print OUT '#<share_top>BIN = $(<share_top>)/bin/$(T_A)',"\n";
print OUT '#endif',"\n";
print OUT ' ',"\n";
print OUT 'ifdef SHARE',"\n";
print OUT 'USR_INCLUDES += -I$(SHARE)/include',"\n";
print OUT 'SHARE_BIN = $(SHARE)/bin/$(T_A)',"\n";
print OUT 'endif',"\n";
print OUT 'ifdef HIDEOS',"\n";
print OUT 'USR_INCLUDES += -I$(HIDEOS)/include',"\n";
print OUT 'HIDEOS_ARCH = $(subst mv,vx,$(T_A))',"\n";
print OUT 'HIDEOS_LIB=$(HIDEOS)/lib/$(HIDEOS_ARCH)',"\n";
print OUT 'HIDEOS_APPS=$(HIDEOS)/usrapps/$(HIDEOS_ARCH)',"\n";
print OUT 'endif',"\n";
print OUT 'ifdef EPICSHIDEOS',"\n";
print OUT 'USR_INCLUDES += -I$(EPICSHIDEOS)/include',"\n";
print OUT 'EPICSHIDEOS_BIN=$(EPICSHIDEOS)/bin/$(T_A)',"\n";
print OUT 'endif',"\n";
print OUT 'ifdef MASTER_IOCAPPS',"\n";
print OUT 'USR_INCLUDES += -I$(MASTER_IOCAPPS)/include',"\n";
print OUT 'MASTER_IOCAPPS_BIN = $(MASTER_IOCAPPS)/bin/$(T_A)',"\n";
print OUT 'endif',"\n";
print OUT 'include $(TOP)/config/CONFIG',"\n";
close OUT;
open OUT, ">RELEASE" or die "Cannot create RELEASE";
print OUT "#RELEASE Location of external products\n";
print OUT "EPICS_BASE=$epics_base\n";
print OUT "#SHARE=\n";
print OUT "#HIDEOS=\n";
print OUT "#EPICSHIDEOS=\n";
print OUT "#MASTER_IOCAPPS=\n";
close OUT;
open OUT, ">RULES_TOP" or die "Cannot create RULES_TOP";
print OUT "#RULES_TOP\n";
print OUT "include \$(EPICS_BASE)/config/RULES_TOP\n";
print OUT "\n";
print OUT "ifdef MASTER_IOCAPPS\n";
print OUT "inc:\tsoftlinks\n";
print OUT "buildInstall:\tsoftlinks\n";
print OUT "\n";
print OUT "softlinks:\n";
print OUT "\t";
print OUT '@echo "softlinks" ; if [ "$(MASTER_IOCAPPS)" ]; then \\';
print OUT "\n";
print OUT "\t";
print OUT 'for DIR in bin lib dbd include man ; do \\';
print OUT "\n";
print OUT "\t";
print OUT '$(TOP)/config/makeSoftLinks $(MASTER_IOCAPPS) $${DIR} ;\\';
print OUT "\n";
print OUT "\t";
print OUT 'done; fi';
print OUT "\n";
print OUT "\n";
print OUT ".PHONY :: softlinks\n";
print OUT "endif\n";
close OUT;
open OUT, ">RULES.iocBoot" or die "Cannot create RULES.iocBoot";
print OUT '#RULES.iocBoot', "\n";
print OUT 'DIRS += $(wildcard ioc*)', "\n";
print OUT 'DIRS += $(wildcard as*)', "\n";
print OUT 'include $(EPICS_BASE)/config/RULES_DIRS', "\n";
print OUT 'ifeq ($(findstring nfsCommands,$(wildcard *)),nfsCommands)', "\n";
print OUT "buildInstall:: nfs.cmd\n";
print OUT "\n";
print OUT 'nfs.cmd: nfsCommands', "\n";
print OUT "\t",'@echo "Creating $@"', "\n";
print OUT "\t",'@$(RM) $@', "\n";
print OUT "\t",'@cat $< >> $@', "\n";
print OUT "\t",'@echo cd \"`\pwd`\" >> $@', "\n";
print OUT "\n";
print OUT 'clean::', "\n";
print OUT "\t",'@$(RM) nfs.cmd', "\n";
print OUT 'endif', "\n";
close OUT;
# Simple config files that just include the BASE version:
foreach $file ( 'RULES.Db', 'RULES.Host', 'RULES.ioc', 'RULES.Vx' ,
'RULES_ARCHS', 'RULES_DIRS')
{
open OUT, ">$file" or die "Cannot create $file";
print OUT "#$file\n";
print OUT "include \$(EPICS_BASE)/config/$file\n";
if ( ($file eq "RULES.Host") || ($file eq "RULES.Vx") ) {
print OUT "inc:: \$(INSTALL_INCREC)\n";
}
close OUT;
}
open OUT, ">makeSoftLinks" or die "Cannot createmakeSoftLinks";
print OUT '#!/bin/sh',"\n";
print OUT '#makeSoftLinks',"\n";
print OUT '#This shell program makes soft links to everything in MASTER_IOCAPPS/bin/*',"\n";
print OUT '#set -xv',"\n";
print OUT '',"\n";
print OUT 'SAVEDIR=$PWD',"\n";
print OUT 'Cleanup() {',"\n";
print OUT ' cd $SAVEDIR',"\n";
print OUT ' rtncode=$1',"\n";
print OUT ' shift 1',"\n";
print OUT ' for MESSAGE',"\n";
print OUT ' do',"\n";
print OUT ' echo "$MESSAGE"',"\n";
print OUT ' done',"\n";
print OUT ' exit $rtncode',"\n";
print OUT '}',"\n";
print OUT 'USAGE="Usage: makeSoftLinks MASTER_IOCAPPS dir"',"\n";
print OUT '',"\n";
print OUT 'if [ $# != 2 ]; then Cleanup 1 "Illegal number args" "$USAGE"; fi;',"\n";
print OUT 'MASTER_IOCAPPS=$1',"\n";
print OUT 'DIR=$2',"\n";
print OUT '',"\n";
print OUT 'if [ ! -d ${MASTER_IOCAPPS}/${DIR} ] ; then Cleanup 0 ; fi',"\n";
print OUT '',"\n";
print OUT 'FROM=${MASTER_IOCAPPS}/${DIR}',"\n";
print OUT 'if [ -z "`ls ${FROM}`" ] ; then Cleanup 0 ; fi',"\n";
print OUT 'if [ ! -d ${DIR} ] ; then',"\n";
print OUT ' echo "mkdir ${DIR}"',"\n";
print OUT ' mkdir ${DIR}',"\n";
print OUT 'fi',"\n";
print OUT 'cd ${DIR}',"\n";
print OUT 'for FILE in `ls ${FROM}`',"\n";
print OUT 'do',"\n";
print OUT ' if [ -d ${FROM}/${FILE} ] ; then',"\n";
print OUT ' $0 ${MASTER_IOCAPPS}/${DIR} ${FILE}',"\n";
print OUT ' elif [ -f ${FROM}/${FILE} ] ; then',"\n";
print OUT ' if [ ! -f "${FILE}" ]; then',"\n";
print OUT ' ln -s ${MASTER_IOCAPPS}/${DIR}/${FILE} ${FILE}',"\n";
print OUT ' fi',"\n";
print OUT ' else',"\n";
print OUT ' echo "${MASTER_IOCAPPS}/${DIR}/${FILE} Illegal."',"\n";
print OUT ' fi',"\n";
print OUT 'done',"\n";
print OUT 'Cleanup 0',"\n";
close OUT;
chdir $startdir or die 'cannot return to start directory';
}
# Generate app dirs (if any names given)
#
foreach $app ( @apps )
{
if (-d "${app}App")
{
print "App '$app' is already there!\n";
next;
}
mkdir "${app}App", 0777;
chdir "${app}App" or die "Cannor create dir ${app}App";
open OUT, ">Makefile" or die "Cannot open Makefile";
print OUT "TOP = ..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "DIRS += \$(wildcard src)\n";
print OUT "DIRS += \$(wildcard *Src*)\n";
print OUT "DIRS += \$(wildcard *Db*)\n";
print OUT "include \$(TOP)/config/RULES_DIRS\n";
close OUT;
mkdir "Db", 0777;
open OUT, ">Db/Makefile" or die "Cannot open Db/Makefile";
print OUT "TOP = ../..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "\n";
print OUT "#following creates xxx.db from xxx.template and xxx.substitutions\n";
print OUT "#DBFROMTEMPLATE += xxx.db\n";
print OUT "\n";
print OUT "#Following creates xxxi.db from xxx.template and xxxi.substitutions\n";
print OUT "#INDDBFROMTEMPLATE += xxxi.db\n";
print OUT "\n";
print OUT "#Following taken care of by local rules\n";
print OUT "#PROD += yyy.db\n";
print OUT "\n";
print OUT "\n";
print OUT "include \$(TOP)/config/RULES.Db\n";
print OUT "\n";
print OUT "#yyy.db: <dependicies for yyy.db\n";
print OUT "#\t<rules to create yyy.db\n";
print OUT "\n";
close OUT;
if ($example)
{
open OUT, ">Db/dbExample.db" or
die "Cannot open Db/dbExample.db";
print OUT "record(ai, \"\$(user):aiExample\")\n";
print OUT "{\n";
print OUT "\tfield(DESC, \"Analog input\")\n";
print OUT "\tfield(INP, \"\$(user):calcExample.VAL NPP NMS\")\n";
print OUT "\tfield(EGUF, \"10\")\n";
print OUT "\tfield(EGU, \"Counts\")\n";
print OUT "\tfield(HOPR, \"10\")\n";
print OUT "\tfield(LOPR, \"0\")\n";
print OUT "\tfield(HIHI, \"8\")\n";
print OUT "\tfield(HIGH, \"6\")\n";
print OUT "\tfield(LOW, \"4\")\n";
print OUT "\tfield(LOLO, \"2\")\n";
print OUT "\tfield(HHSV, \"MAJOR\")\n";
print OUT "\tfield(HSV, \"MINOR\")\n";
print OUT "\tfield(LSV, \"MINOR\")\n";
print OUT "\tfield(LLSV, \"MAJOR\")\n";
print OUT "}\n";
print OUT "record(calc, \"\$(user):calcExample\")\n";
print OUT "{\n";
print OUT "\tfield(DESC, \"Counter\")\n";
print OUT "\tfield(SCAN, \"1 second\")\n";
print OUT "\tfield(FLNK, \"\$(user):aiExample\")\n";
print OUT "\tfield(CALC, \"(A<B)?(A+C):D\")\n";
print OUT "\tfield(INPA, \"\$(user):calcExample.VAL NPP NMS\")\n";
print OUT "\tfield(INPB, \"9\")\n";
print OUT "\tfield(INPC, \"1\")\n";
print OUT "\tfield(INPD, \"0\")\n";
print OUT "\tfield(EGU, \"Counts\")\n";
print OUT "\tfield(HOPR, \"10\")\n";
print OUT "\tfield(HIHI, \"8\")\n";
print OUT "\tfield(HIGH, \"6\")\n";
print OUT "\tfield(LOW, \"4\")\n";
print OUT "\tfield(LOLO, \"2\")\n";
print OUT "\tfield(HHSV, \"MAJOR\")\n";
print OUT "\tfield(HSV, \"MINOR\")\n";
print OUT "\tfield(LSV, \"MINOR\")\n";
print OUT "\tfield(LLSV, \"MAJOR\")\n";
print OUT "}\n";
print OUT "record(xxx, \"\$(user):xxxExample\")\n";
print OUT "{\n";
print OUT "\tfield(DESC, \"xxx record\")\n";
print OUT "\tfield(EGU, \"Counts\")\n";
print OUT "\tfield(HOPR, \"10\")\n";
print OUT "\tfield(HIHI, \"8\")\n";
print OUT "\tfield(HIGH, \"6\")\n";
print OUT "\tfield(LOW, \"4\")\n";
print OUT "\tfield(LOLO, \"2\")\n";
print OUT "\tfield(HHSV, \"MAJOR\")\n";
print OUT "\tfield(HSV, \"MINOR\")\n";
print OUT "\tfield(LSV, \"MINOR\")\n";
print OUT "\tfield(LLSV, \"MAJOR\")\n";
print OUT "}\n";
}
mkdir 'src', 0777;
open OUT, ">src/Makefile" or die "Cannot open src/Makefile";
print OUT "TOP=../..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "include \$(TOP)/config/RULES_ARCHS\n";
close OUT;
open OUT, ">src/Makefile.Vx" or die "Cannot open src/Makefile.Vx";
print OUT "# Makefile.Vx\n";
print OUT "TOP = ../../..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "#----------------------------------------\n";
print OUT "# ADD MACRO DEFINITIONS AFTER THIS LINE\n";
# OUT still set to Makefile.Vx
if ( $example)
{
print OUT "RECTYPES += xxxRecord.h\n";
print OUT "USER_DBDFLAGS += -I .. -I \$(EPICS_BASE)/dbd\n";
print OUT "DBDEXPAND = ${app}Include.dbd\n";
print OUT "DBDNAME = ${app}App.dbd\n";
print OUT "SRCS.c += ../xxxRecord.c\n";
print OUT "SRCS.c += ../devXxxSoft.c\n";
print OUT "\n";
print OUT "include ../baseLIBOBJS\n";
print OUT "LIBOBJS += xxxRecord.o\n";
print OUT "LIBOBJS += devXxxSoft.o\n";
print OUT "LIBOBJS += sncExample.o\n";
print OUT "LIBNAME = ${app}Lib\n";
print OUT "INSTALLS += vxWorks vxWorks.sym iocCore seq\n";
}
else
{
print OUT "#RECTYPES += anyRecord.h\n";
print OUT "USER_DBDFLAGS += -I .. -I \$(EPICS_BASE)/dbd\n";
print OUT "#DBDEXPAND = ${app}Include.dbd\n";
print OUT "#DBDNAME = ${app}App.dbd\n";
print OUT "#SRCS.c += ../anysource.c\n";
print OUT "\n";
print OUT "#include ../baseLIBOBJS\n";
print OUT "#LIBOBJS += anysource.o\n";
print OUT "#LIBNAME = ${app}Lib\n";
print OUT "#INSTALLS += vxWorks vxWorks.sym iocCore seq\n";
}
# OUT still set to Makefile.Vx...
print OUT "\n";
print OUT "#\tNote that the command line that builds the\n";
print OUT "#\tlibrary \$(LIBNAME) may be HUGE (>3kB)\n";
print OUT "#\n";
print OUT "\n";
print OUT "include \$(TOP)/config/RULES.Vx\n";
print OUT "#----------------------------------------\n";
print OUT "# ADD RULES AFTER THIS LINE\n";
close OUT;
open OUT, ">src/Makefile.Host"
or die "Cannot open src/Makefile.Host";
print OUT "# Makefile.Host\n";
print OUT "TOP = ../../..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "#----------------------------------------\n";
print OUT "# ADD MACRO DEFINITIONS AFTER THIS LINE\n";
print OUT "\n";
print OUT "#USR_CFLAGS += \n";
print OUT "PROD_LIBS_DEFAULT += m\n";
print OUT "PROD_LIBS_WIN32 := -nil-\n";
print OUT "PROD_LIBS += ca\n";
print OUT "PROD_LIBS += Db\n";
print OUT "PROD_LIBS += Com\n";
print OUT "\n";
if ($example)
{
print OUT "PROD += caExample\n";
}
else
{
print OUT "#PROD += xxx\n";
}
# OUT still set to src/Makefile.Host...
print OUT "\n";
print OUT "include \$(TOP)/config/RULES.Host\n";
print OUT "#----------------------------------------\n";
print OUT "# ADD RULES AFTER THIS LINE\n";
close OUT;
open OUT, ">src/${app}Include.dbd"
or die "Cannot open src/${app}Include.dbd";
print OUT "include \"base.dbd\"\n";
if ($example)
{
print OUT "include \"xxxRecord.dbd\"\n";
print OUT "device(xxx,CONSTANT,devXxxSoft,\"SoftChannel\")\n";
}
else
{
print OUT "#private database definitions go here\n";
print OUT "#device(xxx,CONSTANT,devXxxSoft,\"SoftChannel\")\n";
}
close OUT;
if ( -f "${epics_base}/dbd/base.dbd" )
{ copy ("${epics_base}/dbd/base.dbd", "src/base.dbd"); }
else
{ print "${epics_base}/dbd/base.dbd does not exist" }
if ( -f "${epics_base}/dbd/baseLIBOBJS" )
{ copy ("${epics_base}/dbd/baseLIBOBJS", "src/baseLIBOBJS"); }
else
{ print "${epics_base}/dbd/baseLIBOBJS does not exist" }
if ($example)
{
open OUT, ">src/caExample.c" or
die "Cannot open src/caExample.c";
print OUT '
/* caExample.c */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "cadef.h"
main (int argc,char **argv)
{
double data;
int status;
chid mychid;
if(argc != 2)
{
fprintf(stderr, "usage: caExample pvname\n");
exit(1);
}
SEVCHK( ca_task_initialize(),"ca_task_initialize");
SEVCHK( ca_search(argv[1],&mychid),"ca_search failure");
SEVCHK( ca_pend_io(5.0),"ca_pend_io failure");
SEVCHK( ca_get(DBR_DOUBLE,mychid,(void *)&data),"ca_get failure");
SEVCHK( ca_pend_io(5.0),"ca_pend_io failure");
printf("%s %f\n",argv[1],data);
return(0);
}
/* EOF caExample.c */
';
close OUT;
open OUT, ">src/xxxRecord.c" or
die "Cannot open src/xxxRecord.c";
print OUT '
/* xxxRecord.c */
/* Example record support module */
#include <vxWorks.h>
#include <stddef.h>
#include <stdio.h>
#include <lstLib.h>
#include <string.h>
#include <alarm.h>
#include <dbEvent.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <devSup.h>
#include <errMdef.h>
#include <recSup.h>
#include <special.h>
#define GEN_SIZE_OFFSET
#include <xxxRecord.h>
#undef GEN_SIZE_OFFSET
/* Create RSET - Record Support Entry Table*/
#define report NULL
#define initialize NULL
static long init_record();
static long process();
#define special NULL
#define get_value NULL
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
static long get_units();
static long get_precision();
#define get_enum_str NULL
#define get_enum_strs NULL
#define put_enum_str NULL
static long get_graphic_double();
static long get_control_double();
static long get_alarm_double();
struct rset xxxRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_units,
get_precision,
get_enum_str,
get_enum_strs,
put_enum_str,
get_graphic_double,
get_control_double,
get_alarm_double};
typedef struct xxxset { /* xxx input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_xxx;
}xxxdset;
static void alarm(xxxRecord *pxxx);
static void monitor(xxxRecord *pxxx);
static long init_record(void *precord,int pass)
{
xxxRecord *pxxx = (xxxRecord *)precord;
xxxdset *pdset;
long status;
if (pass==0) return(0);
if(!(pdset = (xxxdset *)(pxxx->dset))) {
recGblRecordError(S_dev_noDSET,(void *)pxxx,"xxx: init_record");
return(S_dev_noDSET);
}
/* must have read_xxx function defined */
if( (pdset->number < 5) || (pdset->read_xxx == NULL) ) {
recGblRecordError(S_dev_missingSup,(void *)pxxx,"xxx: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(pxxx))) return(status);
}
return(0);
}
static long process(void *precord)
{
xxxRecord *pxxx = (xxxRecord *)precord;
xxxdset *pdset = (xxxdset *)(pxxx->dset);
long status;
unsigned char pact=pxxx->pact;
if( (pdset==NULL) || (pdset->read_xxx==NULL) ) {
pxxx->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)pxxx,"read_xxx");
return(S_dev_missingSup);
}
/* pact must not be set until after calling device support */
status=(*pdset->read_xxx)(pxxx);
/* check if device support set pact */
if ( !pact && pxxx->pact ) return(0);
pxxx->pact = TRUE;
recGblGetTimeStamp(pxxx);
/* check for alarms */
alarm(pxxx);
/* check event list */
monitor(pxxx);
/* process the forward scan link record */
recGblFwdLink(pxxx);
pxxx->pact=FALSE;
return(status);
}
static long get_units(DBADDR *paddr, char *units)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
strncpy(units,pxxx->egu,DB_UNITS_SIZE);
return(0);
}
static long get_precision(DBADDR *paddr, long *precision)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
*precision = pxxx->prec;
if(paddr->pfield == (void *)&pxxx->val) return(0);
recGblGetPrec(paddr,precision);
return(0);
}
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == xxxRecordVAL
|| fieldIndex == xxxRecordHIHI
|| fieldIndex == xxxRecordHIGH
|| fieldIndex == xxxRecordLOW
|| fieldIndex == xxxRecordLOLO
|| fieldIndex == xxxRecordHOPR
|| fieldIndex == xxxRecordLOPR) {
pgd->upper_disp_limit = pxxx->hopr;
pgd->lower_disp_limit = pxxx->lopr;
} else recGblGetGraphicDouble(paddr,pgd);
return(0);
}
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == xxxRecordVAL
|| fieldIndex == xxxRecordHIHI
|| fieldIndex == xxxRecordHIGH
|| fieldIndex == xxxRecordLOW
|| fieldIndex == xxxRecordLOLO) {
pcd->upper_ctrl_limit = pxxx->hopr;
pcd->lower_ctrl_limit = pxxx->lopr;
} else recGblGetControlDouble(paddr,pcd);
return(0);
}
static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == xxxRecordVAL) {
pad->upper_alarm_limit = pxxx->hihi;
pad->upper_warning_limit = pxxx->high;
pad->lower_warning_limit = pxxx->low;
pad->lower_alarm_limit = pxxx->lolo;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
}
static void alarm(xxxRecord *pxxx)
{
double val;
float hyst, lalm, hihi, high, low, lolo;
unsigned short hhsv, llsv, hsv, lsv;
if(pxxx->udf == TRUE ){
recGblSetSevr(pxxx,UDF_ALARM,INVALID_ALARM);
return;
}
hihi = pxxx->hihi; lolo = pxxx->lolo; high = pxxx->high; low = pxxx->low;
hhsv = pxxx->hhsv; llsv = pxxx->llsv; hsv = pxxx->hsv; lsv = pxxx->lsv;
val = pxxx->val; hyst = pxxx->hyst; lalm = pxxx->lalm;
/* alarm condition hihi */
if (hhsv && (val >= hihi || ((lalm==hihi) && (val >= hihi-hyst)))){
if (recGblSetSevr(pxxx,HIHI_ALARM,pxxx->hhsv)) pxxx->lalm = hihi;
return;
}
/* alarm condition lolo */
if (llsv && (val <= lolo || ((lalm==lolo) && (val <= lolo+hyst)))){
if (recGblSetSevr(pxxx,LOLO_ALARM,pxxx->llsv)) pxxx->lalm = lolo;
return;
}
/* alarm condition high */
if (hsv && (val >= high || ((lalm==high) && (val >= high-hyst)))){
if (recGblSetSevr(pxxx,HIGH_ALARM,pxxx->hsv)) pxxx->lalm = high;
return;
}
/* alarm condition low */
if (lsv && (val <= low || ((lalm==low) && (val <= low+hyst)))){
if (recGblSetSevr(pxxx,LOW_ALARM,pxxx->lsv)) pxxx->lalm = low;
return;
}
/* we get here only if val is out of alarm by at least hyst */
pxxx->lalm = val;
return;
}
static void monitor(xxxRecord *pxxx)
{
unsigned short monitor_mask;
double delta;
monitor_mask = recGblResetAlarms(pxxx);
/* check for value change */
delta = pxxx->mlst - pxxx->val;
if(delta<0.0) delta = -delta;
if (delta > pxxx->mdel) {
/* post events for value change */
monitor_mask |= DBE_VALUE;
/* update last value monitored */
pxxx->mlst = pxxx->val;
}
/* check for archive change */
delta = pxxx->alst - pxxx->val;
if(delta<0.0) delta = -delta;
if (delta > pxxx->adel) {
/* post events on value field for archive change */
monitor_mask |= DBE_LOG;
/* update last archive value monitored */
pxxx->alst = pxxx->val;
}
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(pxxx,&pxxx->val,monitor_mask);
}
return;
}
'; # END of xxxRecord.c
close OUT;
open OUT, ">src/xxxRecord.dbd" or
die "Cannot open src/xxxRecord.dbd";
print OUT '
recordtype(xxx) {
include "dbCommon.dbd"
field(VAL,DBF_DOUBLE) {
prompt("Current EGU Value")
asl(ASL0)
pp(TRUE)
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup(GUI_INPUTS)
special(SPC_NOMOD)
interest(1)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup(GUI_DISPLAY)
interest(1)
size(16)
}
field(HOPR,DBF_FLOAT) {
prompt("High Operating Range")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(LOPR,DBF_FLOAT) {
prompt("Low Operating Range")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(HIHI,DBF_FLOAT) {
prompt("Hihi Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(LOLO,DBF_FLOAT) {
prompt("Lolo Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(HIGH,DBF_FLOAT) {
prompt("High Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(LOW,DBF_FLOAT) {
prompt("Low Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup(GUI_ALARMS)
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
}
'; # END of xxxRecord.dbd
open OUT, ">src/devXxxSoft.c" or
die "Cannot open src/devXxxSoft.c";
print OUT '
/* devXxxSoft.c */
/* Example device support module */
#include <vxWorks.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <alarm.h>
#include <cvtTable.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <recSup.h>
#include <devSup.h>
#include <link.h>
#include <xxxRecord.h>
/*Create the dset for devXxxSoft */
static long init_record();
static long read_xxx();
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_xxx;
}devXxxSoft={
5,
NULL,
NULL,
init_record,
NULL,
read_xxx,
};
static long init_record(pxxx)
struct xxxRecord *pxxx;
{
if(recGblInitConstantLink(&pxxx->inp,DBF_DOUBLE,&pxxx->val))
pxxx->udf = FALSE;
return(0);
}
static long read_xxx(pxxx)
struct xxxRecord *pxxx;
{
long status;
status = dbGetLink(&(pxxx->inp),DBF_DOUBLE, &(pxxx->val),0,0);
/*If return was succesful then set undefined false*/
if(!status) pxxx->udf = FALSE;
return(0);
}
'; # END of devXxxSoft.c
open OUT, ">src/sncExample.st" or
die "Cannot open src/sncExample.st";
print OUT "program snctest\n";
print OUT "float v;\n";
print OUT "assign v to \"${user}:xxxExample\";\n";
print OUT 'monitor v;
ss ss1
{
state low
{
when(v>5.0)
{
printf("changing to high\n");
} state high
when(delay(.1))
{
} state low
}
state high
{
when(v<=5.0)
{
printf("changing to low\n");
} state low
when(delay(.1))
{
} state high
}
}
'; # END of sncExample.st
}
chdir $startdir;
unless (-d 'iocBoot')
{
mkdir iocBoot, 0777;
open OUT, ">iocBoot/Makefile"
or die "Cannot open iocBoot/Makefile";
print OUT "TOP = ..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "include \$(TOP)/config/RULES.iocBoot\n";
close OUT;
open OUT, ">iocBoot/nfsCommands"
or die "Cannot open iocBoot/nfsCommands";
print OUT '# nfs Commands',"\n";
print OUT '#Add commands like the following for each host',"\n";
print OUT 'hostAdd("<host>,"xx.xx.xx.xx")', "\n";
print OUT 'nfsMountAll("<host>")', "\n";
close OUT;
}
# generate ioc stuff for this app?
next if -d "iocBoot/ioc$app";
print "What architecture do you want to use for your IOC?\n";
print "e.g. pc486, mv167, ... >";
$arch=<STDIN>;
chomp $arch;
mkdir "iocBoot/ioc$app", 0777;
chdir "iocBoot/ioc$app" or die "Cannot create iocBoot/ioc$app";
open OUT, ">Makefile" or die "Cannot open Makefile";
print OUT "TOP = ../..\n";
print OUT "include \$(TOP)/config/CONFIG_APP\n";
print OUT "ARCH = $arch\n";
print OUT "include \$(TOP)/config/RULES.ioc\n";
close OUT;
open OUT, ">st.cmd" or die "Cannot open st.cmd";
print OUT "# Example vxWorks startup file\n";
print OUT "#Following must be added for many board support packages\n";
print OUT "#cd <full path to boot directory>\n";
print OUT "#cd \"" . UNIXStyleName($startdir) . "\/iocBoot\/ioc$app" . "\"\n";
print OUT "\n";
print OUT "#Following will use NFS for file access\n";
print OUT "#< ../nfs.cmd\n";
print OUT "#cd \"ioc$app\"\n";
print OUT "\n";
print OUT "ld < bin/iocCore\n";
print OUT "ld < bin/seq\n";
print OUT "ld < bin/${app}Lib\n";
print OUT "\n";
print OUT "dbLoadDatabase(\"dbd/${app}App.dbd\")\n";
if ($example)
{
print OUT
"dbLoadRecords(\"${app}App/Db/dbExample.db\",\"user=${user}\")\n";
print OUT "iocInit\n";
print OUT "seq &snctest\n";
}
else
{
print OUT "#dbLoadRecords(\"${app}App/Db/xxx.db\",\"user=${user}\")\n";
print OUT "iocInit\n";
print OUT "#start sequence programs\n";
print OUT "#seq &sncxxx\n";
}
close OUT;
chdir $startdir;
}
# Cleanup (return-code [ messsage-line1, line 2, ... ])
sub Cleanup
{
my ($rtncode, @message) = @_;
chdir $startdir;
print "Usage: $0 [-b EPICS base dir] [-e] {appname ...}\n\n"
if ($rtncode != 0);
foreach $line ( @message )
{
print "$line\n";
}
exit $rtncode;
}
sub GetHome # no args
{
my ($home);
# add to this list if new possibilities arise,
# currently it's UNIX and WIN32:
$home=$ENV{HOME} || $ENV{HOMEPATH};
die "cannot locate home directory" unless $home;
return $home;
}
sub UNIXStyleName
{
my ($name) = @_;
$name =~ s'^[a-z]:''i; # remove driver letter
$name =~ s'\\'/'g; # change slashed
return $name;
}
sub GetUser # no args
{
my ($user);
# add to this list if new possibilities arise,
# currently it's UNIX and WIN32:
$user=$ENV{USER} || $ENV{USERNAME};
unless ($user)
{
print "I cannot figure out your user name.\n";
print "What shall you be called ?\n";
print ">";
$user = <STDIN>;
chomp $user;
}
die "No user name" unless $user;
return $user;
}
sub Wait # (seconds)
{
my ($secs, $now, $i) = @_;
$now=time;
while (time() < $now+$secs)
{
$i=1234; # maybe the worst busy wait ever written
}
}