Compare commits
11 Commits
R3.14.12.4
...
R3.14.12.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3009091875 | ||
|
|
6a0d5e0e87 | ||
|
|
97636a45e0 | ||
|
|
a50c66b6ff | ||
|
|
88ae947c84 | ||
|
|
22540ac743 | ||
|
|
197e992241 | ||
|
|
b0cf5c256a | ||
|
|
76e967c960 | ||
|
|
4ac35ab85c | ||
|
|
4209abe2cf |
@@ -1,17 +1,13 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE Versions 3.13.7
|
||||
# and higher are distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
#
|
||||
# $Revision-Id$
|
||||
#
|
||||
# The developer may edit this file.
|
||||
# assume T_A is the host arch if not specified
|
||||
|
||||
#
|
||||
# Common build definitions
|
||||
@@ -89,8 +85,6 @@ endif
|
||||
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
|
||||
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
endif
|
||||
|
||||
# Include <top>/cfg/CONFIG* definitions from tops defined in RELEASE* files
|
||||
#
|
||||
ifneq ($(CONFIG),$(TOP)/configure)
|
||||
@@ -103,12 +97,12 @@ endif
|
||||
|
||||
# Include $(INSTALL_CFG)/CONFIG* definitions
|
||||
#
|
||||
ifndef T_A
|
||||
TOP_CFG_CONFIGS = $(wildcard $(INSTALL_CFG)/CONFIG*)
|
||||
ifneq ($(TOP_CFG_CONFIGS),)
|
||||
include $(TOP_CFG_CONFIGS)
|
||||
endif
|
||||
endif
|
||||
|
||||
endif # ifdef T_A
|
||||
|
||||
# User specific definitions
|
||||
#
|
||||
@@ -119,22 +113,3 @@ ifdef T_A
|
||||
-include $(HOME)/configure/CONFIG_USER.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
||||
|
||||
# All options
|
||||
# may be overridden here.
|
||||
#
|
||||
# EXAMPLES
|
||||
# --------
|
||||
# Build client objects statically ? must be either YES or NO
|
||||
#STATIC_BUILD=NO
|
||||
# Host build optimization, must be either YES or NO
|
||||
#HOST_OPT=YES
|
||||
# Cross build optimization, must be either YES or NO
|
||||
#CROSS_OPT=YES
|
||||
# Generate Verbose Compiler Warnings for host build, must be either YES or NO
|
||||
#HOST_WARN=YES
|
||||
# Generate Verbose Compiler Warnings for cross compile builds, must be either YES or NO
|
||||
#CROSS_WARN=YES
|
||||
#etc.
|
||||
|
||||
#CROSS_COMPILER_TARGET_ARCHS=vxWorks-68040
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ EPICS_PATCH_LEVEL = 4
|
||||
#EPICS_DEV_SNAPSHOT=-pre1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-pre2
|
||||
#EPICS_DEV_SNAPSHOT=-pre2-DEV
|
||||
EPICS_DEV_SNAPSHOT=-rc1
|
||||
#EPICS_DEV_SNAPSHOT=-rc1
|
||||
#EPICS_DEV_SNAPSHOT=-rc1-DEV
|
||||
#EPICS_DEV_SNAPSHOT=-rc2
|
||||
#EPICS_DEV_SNAPSHOT=-rc2-DEV
|
||||
#EPICS_DEV_SNAPSHOT=
|
||||
EPICS_DEV_SNAPSHOT=
|
||||
|
||||
# No changes should be needed below here
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne
|
||||
# Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
# $Revision-Id$
|
||||
#
|
||||
@@ -12,7 +12,7 @@
|
||||
#
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# Module developers can now define a new type of file, e.g. ABC,
|
||||
# Module developers can now define a new type of file, e.g. ABC,
|
||||
# so that files of type ABC will be installed into a directory
|
||||
# defined by INSTALL_ABC. This is done by creating a new CONFIG<name>
|
||||
# file, e.g. CONFIG_ABC, with the following lines:
|
||||
@@ -24,8 +24,14 @@
|
||||
# $(INSTALL_LOCATION). The file type ABC should be target
|
||||
# architecture independent (alh files, medm files, edm files).
|
||||
#
|
||||
# Optional rules necessary for files of type ABC should be put in
|
||||
# a RULES_ABC file.
|
||||
# Files of type ABC are then installed into the INSTALL_ABC
|
||||
# directory by adding a line like the following to a Makefile.
|
||||
#
|
||||
# ABC += <filename1> <filename2> <filename3>
|
||||
#
|
||||
# Rules necessary to create files of type ABC should be put in
|
||||
# a RULES_ABC file. Variables used by those rules should appear
|
||||
# in a CONFIG_ABC file.
|
||||
#
|
||||
# The module developer installs new CONFIG* or RULES* files
|
||||
# into the directory $(INSTALL_LOCATION)/cfg by including the
|
||||
@@ -33,16 +39,11 @@
|
||||
#
|
||||
# CFG += CONFIG_ABC RULES_ABC
|
||||
#
|
||||
# Files of type ABC are installed into INSTALL_ABC directory
|
||||
# by adding a line like the following to a Makefile.
|
||||
#
|
||||
# ABC += <filename1> <filename2> <filename3>
|
||||
#
|
||||
# Files in $(INSTALL_LOCATION)/cfg directory are now included by
|
||||
# the base config files so the definitions and rules are available
|
||||
# for use by later src directory Makefiles in the same module or
|
||||
# by other modules with a RELEASE line pointing to the TOP of
|
||||
# the module with RULES_ABC.
|
||||
# CONFIG and RULES files in the $(INSTALL_LOCATION)/cfg directory
|
||||
# are included by the Base config files so their definitions and
|
||||
# rules are available for use by later src directory Makefiles in
|
||||
# the same module, or by other modules with a RELEASE line that
|
||||
# points to the TOP of the module providing these files.
|
||||
|
||||
FILE_TYPE += ADL
|
||||
INSTALL_ADL = $(INSTALL_LOCATION)/adl
|
||||
@@ -59,6 +60,6 @@ INSTALL_EDL = $(INSTALL_LOCATION)/edl
|
||||
FILE_TYPE += PERL_MODULES
|
||||
INSTALL_PERL_MODULES = $(INSTALL_LOCATION_LIB)/perl
|
||||
|
||||
INSTALLS_CFG= $(CFG:%= $(INSTALL_CFG)/%)
|
||||
INSTALLS_CFG = $(CFG:%= $(INSTALL_CFG)/%)
|
||||
DIRECTORY_TARGETS += $(foreach type, $(FILE_TYPE),$(INSTALL_$(type)))
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne
|
||||
# Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
|
||||
# National Laboratory.
|
||||
# Copyright (c) 2002 The Regents of the University of California, as
|
||||
# Operator of Los Alamos National Laboratory.
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
# in the file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
# $Revision-Id$
|
||||
#
|
||||
@@ -36,13 +36,11 @@ endif
|
||||
endif
|
||||
|
||||
#---------------------------------------------
|
||||
# Include existing and new $(INSTALL_CFG)/* definitions
|
||||
# Include our own $(INSTALL_CFG)/RULES* definitions
|
||||
#
|
||||
TOP_CFG_FILES = $(sort $(wildcard $(INSTALL_CFG)/RULES*) \
|
||||
$(wildcard $(INSTALL_CFG)/CONFIG*) \
|
||||
$(addprefix $(INSTALL_CFG)/,$(CFG)))
|
||||
ifneq ($(TOP_CFG_FILES),)
|
||||
include $(TOP_CFG_FILES)
|
||||
TOP_CFG_RULES = $(wildcard $(INSTALL_CFG)/RULES*)
|
||||
ifneq ($(TOP_CFG_RULES),)
|
||||
include $(TOP_CFG_RULES)
|
||||
endif
|
||||
|
||||
#---------------------------------------------------------------
|
||||
|
||||
@@ -1,19 +1,56 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
|
||||
<title>EPICS Base R3.14.12.4-rc1 Release Notes</title>
|
||||
<title>EPICS Base R3.14.12.4 Release Notes</title>
|
||||
</head>
|
||||
|
||||
<body lang="en">
|
||||
<h1 align="center">EPICS Base Release 3.14.12.4-rc1</h1>
|
||||
<h1 align="center">EPICS Base Release 3.14.12.4</h1>
|
||||
|
||||
<h2 align="center">Changes between 3.14.12.3 and 3.14.12.4</h2>
|
||||
|
||||
<!-- Insert new items immediately below here ... -->
|
||||
|
||||
<h3>New test for environment variables</h3>
|
||||
|
||||
<p>A new test program epicsEnvTest has been added to the libCom tests which
|
||||
checks environment variable APIs. It was written to confirm that threads see
|
||||
environment variable values that have been set in their parent thread. VxWorks
|
||||
6.x boot images must be configured with ENV_VAR_USE_HOOKS set to FALSE for the
|
||||
correct behaviour to occur (a test failure on VxWorks explains this).</p>
|
||||
|
||||
<h3>Inclusion of <top>/cfg/* files refined</h3>
|
||||
|
||||
<p>The way the build system includes files installed in the <top>/cfg/*
|
||||
directory has been cleaned up. Files whose names begin with CONFIG will now get
|
||||
included by the CONFIG step, and files whose names begin with RULES will get
|
||||
included in the RULES step. These files are only ever included when GNUMake is
|
||||
working in an application build (O.) directory and T_A is defined, so they
|
||||
cannot be used to create generic build targets at other levels.</p>
|
||||
|
||||
<p>Files whose names don't start with either CONFIG or RULES are no longer
|
||||
included automatically, but such files can still be installed into
|
||||
<top>/cfg by naming them in the CFG variable.</p>
|
||||
|
||||
<h3>Fixed iocsh stream redirection for several commands</h3>
|
||||
|
||||
<p>A number of iocsh commands did not respond correctly to redirection of their
|
||||
output using the iocsh '>file' or '2>error-file' syntax, and redirecting an
|
||||
empty command could create files with garbage names. There may still be a few
|
||||
commands that do not properly redirect their output, please notify the core
|
||||
developers if you discover any. Thanks to Eric Norum for the iocsh changes.</p>
|
||||
|
||||
<p>For externally developed commands, the simplest way to support redirection in
|
||||
your C/C++ code is to <tt>#include "epicsStdioRedirect.h"</tt> instead of
|
||||
<tt>stdio.h</tt>.</p>
|
||||
|
||||
<h3>Fixed crash on loading record instance of unknown type</h3>
|
||||
|
||||
<p>Fixed segfault when dbLoadRecords tried to load a record of a type that was
|
||||
not defined in its DBD files.</p>
|
||||
|
||||
<h3>Hex literal support in epicStrtod()</h3>
|
||||
|
||||
<p>Some OS implementations of the standard C library routine strtod() do not
|
||||
@@ -26,6 +63,12 @@ Dirk Zimoch for suggesting this change.</p>
|
||||
|
||||
<p>Both windows-x64-mingw and cygwin-x86_64 build targets are now provided.</p>
|
||||
|
||||
<h3>Windows build issues</h3>
|
||||
|
||||
<p>Thanks to Peter Heesterman for suggesting a number of small changes that
|
||||
clean up build issues on Windows, mostly related to symbol import and export
|
||||
to/from DLLs.</p>
|
||||
|
||||
<h3>CAS: GDD Reference Count Underflow</h3>
|
||||
|
||||
<p>Thanks to Bruce Hill a source of an underflow in a GDD reference count in the
|
||||
@@ -34,7 +77,9 @@ CAS code has been fixed.</p>
|
||||
<h3>Support for Apple Xcode 5.0</h3>
|
||||
|
||||
<p>This adds the ability to build for iOS 7.0 and the ARMv8 64-bit CPU on the
|
||||
newest iPhone 5S device.</p>
|
||||
newest iPhone 5S device. Unfortunately the Xcode upgrade breaks the build of the
|
||||
ios-x86 simulator target, although the ios-arm target successfully builds code
|
||||
which runs fine on the real hardware.</p>
|
||||
|
||||
<h3>Reading TSEL field</h3>
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "envDefs.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "epicsStdioRedirect.h"
|
||||
#include "errlog.h"
|
||||
#include "osiWireFormat.h"
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* simple stub for testing monitors
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "epicsStdioRedirect.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "cadef.h"
|
||||
|
||||
@@ -112,8 +112,6 @@ static void yyerrorAbort(char *str)
|
||||
{
|
||||
yyerror(str);
|
||||
yyAbort = TRUE;
|
||||
while (ellCount(&tempList))
|
||||
popFirstTemp();
|
||||
}
|
||||
|
||||
static void allocTemp(void *pvoid)
|
||||
@@ -256,6 +254,11 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
|
||||
my_buffer_ptr = my_buffer;
|
||||
ellAdd(&inputFileList,&pinputFile->node);
|
||||
status = pvt_yy_parse();
|
||||
|
||||
if (yyAbort)
|
||||
while (ellCount(&tempList))
|
||||
popFirstTemp();
|
||||
|
||||
dbFreePath(pdbbase);
|
||||
if(!status) { /*add RTYP and VERS as an attribute */
|
||||
DBENTRY dbEntry;
|
||||
@@ -923,7 +926,7 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
allocTemp(pdbentry);
|
||||
status = dbFindRecordType(pdbentry, recordType);
|
||||
if (status) {
|
||||
epicsPrintf("Record \"%s\" is of unknown type \"%s\" - ",
|
||||
epicsPrintf("Record \"%s\" is of unknown type \"%s\"\n",
|
||||
name, recordType);
|
||||
yyerrorAbort(NULL);
|
||||
return;
|
||||
@@ -932,8 +935,8 @@ static void dbRecordHead(char *recordType, char *name, int visible)
|
||||
status = dbCreateRecord(pdbentry,name);
|
||||
if (status==S_dbLib_recExists) {
|
||||
if (strcmp(recordType, dbGetRecordTypeName(pdbentry))!=0) {
|
||||
epicsPrintf("Record \"%s\" already defined with different type "
|
||||
"\"%s\"\n", name, dbGetRecordTypeName(pdbentry));
|
||||
epicsPrintf("Record \"%s\" of type \"%s\" redefined with new type "
|
||||
"\"%s\"\n", name, dbGetRecordTypeName(pdbentry), recordType);
|
||||
yyerror(NULL);
|
||||
duplicate = TRUE;
|
||||
return;
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
/* $Revision-Id$ */
|
||||
|
||||
/* Author: Marty Kraimer Date: 04-07-94 */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
@@ -18,6 +17,7 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#include "cantProceed.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsStdioRedirect.h"
|
||||
#include "epicsString.h"
|
||||
#include "dbDefs.h"
|
||||
#include "ellLib.h"
|
||||
@@ -34,13 +34,14 @@ typedef struct gphPvt {
|
||||
#define MIN_SIZE 256
|
||||
#define DEFAULT_SIZE 512
|
||||
#define MAX_SIZE 65536
|
||||
|
||||
|
||||
|
||||
void epicsShareAPI gphInitPvt(gphPvt **ppvt, int size)
|
||||
{
|
||||
gphPvt *pgphPvt;
|
||||
|
||||
if (size & (size - 1)) {
|
||||
printf("gphInitPvt: %d is not a power of 2\n", size);
|
||||
fprintf(stderr, "gphInitPvt: %d is not a power of 2\n", size);
|
||||
size = DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ GPHENTRY * epicsShareAPI gphFind(gphPvt *pgphPvt, const char *name, void *pvtid)
|
||||
epicsMutexUnlock(pgphPvt->lock);
|
||||
return pgphNode;
|
||||
}
|
||||
|
||||
|
||||
GPHENTRY * epicsShareAPI gphAdd(gphPvt *pgphPvt, const char *name, void *pvtid)
|
||||
{
|
||||
ELLLIST **paplist;
|
||||
@@ -127,7 +128,7 @@ GPHENTRY * epicsShareAPI gphAdd(gphPvt *pgphPvt, const char *name, void *pvtid)
|
||||
epicsMutexUnlock(pgphPvt->lock);
|
||||
return (pgphNode);
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI gphDelete(gphPvt *pgphPvt, const char *name, void *pvtid)
|
||||
{
|
||||
ELLLIST **paplist;
|
||||
@@ -161,7 +162,7 @@ void epicsShareAPI gphDelete(gphPvt *pgphPvt, const char *name, void *pvtid)
|
||||
epicsMutexUnlock(pgphPvt->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI gphFreeMem(gphPvt *pgphPvt)
|
||||
{
|
||||
ELLLIST **paplist;
|
||||
@@ -203,9 +204,10 @@ void epicsShareAPI gphDumpFP(FILE *fp, gphPvt *pgphPvt)
|
||||
ELLLIST **paplist;
|
||||
int h;
|
||||
|
||||
if (pgphPvt == NULL) return;
|
||||
if (pgphPvt == NULL)
|
||||
return;
|
||||
|
||||
printf("Hash table has %d buckets", pgphPvt->size);
|
||||
fprintf(fp, "Hash table has %d buckets", pgphPvt->size);
|
||||
|
||||
paplist = pgphPvt->paplist;
|
||||
for (h = 0; h < pgphPvt->size; h++) {
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* iocsh.cpp */
|
||||
@@ -68,6 +67,7 @@ struct iocshRedirect {
|
||||
const char *mode;
|
||||
FILE *fp;
|
||||
FILE *oldFp;
|
||||
int mustRestore;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -101,7 +101,8 @@ iocshTableUnlock (void)
|
||||
/*
|
||||
* Register a command
|
||||
*/
|
||||
void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef, iocshCallFunc func)
|
||||
void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef,
|
||||
iocshCallFunc func)
|
||||
{
|
||||
struct iocshCommand *l, *p, *n;
|
||||
int i;
|
||||
@@ -118,7 +119,8 @@ void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef, iocshCallFu
|
||||
if (i < 0)
|
||||
break;
|
||||
}
|
||||
n = (struct iocshCommand *)callocMustSucceed (1, sizeof *n, "iocshRegister");
|
||||
n = (struct iocshCommand *) callocMustSucceed (1, sizeof *n,
|
||||
"iocshRegister");
|
||||
if (!registryAdd(iocshCmdID, piocshFuncDef->name, (void *)n)) {
|
||||
free (n);
|
||||
iocshTableUnlock ();
|
||||
@@ -162,7 +164,8 @@ void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef)
|
||||
for (l = NULL, p = iocshVariableHead ; p != NULL ; l = p, p = p->next) {
|
||||
i = strcmp (piocshVarDef->name, p->pVarDef->name);
|
||||
if (i == 0) {
|
||||
errlogPrintf("Warning -- iocshRegisterVariable redefining %s.\n", piocshVarDef->name);
|
||||
errlogPrintf("Warning: iocshRegisterVariable redefining %s.\n",
|
||||
piocshVarDef->name);
|
||||
p->pVarDef = piocshVarDef;
|
||||
found = 1;
|
||||
break;
|
||||
@@ -171,11 +174,13 @@ void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef)
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
n = (struct iocshVariable *)callocMustSucceed(1, sizeof *n, "iocshRegisterVariable");
|
||||
n = (struct iocshVariable *) callocMustSucceed(1, sizeof *n,
|
||||
"iocshRegisterVariable");
|
||||
if (!registryAdd(iocshVarID, piocshVarDef->name, (void *)n)) {
|
||||
free(n);
|
||||
iocshTableUnlock();
|
||||
errlogPrintf("iocshRegisterVariable failed to add %s.\n", piocshVarDef->name);
|
||||
errlogPrintf("iocshRegisterVariable failed to add %s.\n",
|
||||
piocshVarDef->name);
|
||||
return;
|
||||
}
|
||||
if (l == NULL) {
|
||||
@@ -225,14 +230,15 @@ showError (const char *filename, int lineno, const char *msg, ...)
|
||||
|
||||
va_start (ap, msg);
|
||||
if (filename)
|
||||
fprintf (stderr, "%s -- Line %d -- ", filename, lineno);
|
||||
vfprintf (stderr, msg, ap);
|
||||
fputc ('\n', stderr);
|
||||
fprintf(epicsGetStderr(), "%s line %d: ", filename, lineno);
|
||||
vfprintf (epicsGetStderr(), msg, ap);
|
||||
fputc ('\n', epicsGetStderr());
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
static int
|
||||
cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const iocshArg *piocshArg)
|
||||
cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf,
|
||||
const iocshArg *piocshArg)
|
||||
{
|
||||
char *endp;
|
||||
|
||||
@@ -245,12 +251,13 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const
|
||||
errno = 0;
|
||||
argBuf->ival = strtoul (arg, &endp, 0);
|
||||
if (errno == ERANGE) {
|
||||
showError (filename, lineno, "Integer '%s' out of range", arg);
|
||||
showError(filename, lineno, "Integer '%s' out of range",
|
||||
arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (*endp) {
|
||||
showError (filename, lineno, "Illegal integer '%s'", arg);
|
||||
showError(filename, lineno, "Illegal integer '%s'", arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +270,7 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const
|
||||
if (arg && *arg) {
|
||||
argBuf->dval = epicsStrtod (arg, &endp);
|
||||
if (*endp) {
|
||||
showError (filename, lineno, "Illegal double '%s'", arg);
|
||||
showError(filename, lineno, "Illegal double '%s'", arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -279,7 +286,7 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const
|
||||
case iocshArgPersistentString:
|
||||
argBuf->sval = epicsStrDup(arg);
|
||||
if (argBuf->sval == NULL) {
|
||||
showError (filename, lineno, "Out of memory");
|
||||
showError(filename, lineno, "Out of memory");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -288,17 +295,18 @@ cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const
|
||||
/* Argument must be missing or 0 or pdbbase */
|
||||
if(!arg || !*arg || (*arg == '0') || (strcmp(arg, "pdbbase") == 0)) {
|
||||
if(!iocshPpdbbase || !*iocshPpdbbase) {
|
||||
showError (filename, lineno, "pdbbase not present");
|
||||
showError(filename, lineno, "pdbbase not present");
|
||||
return 0;
|
||||
}
|
||||
argBuf->vval = *iocshPpdbbase;
|
||||
break;
|
||||
}
|
||||
showError (filename, lineno, "Expecting 'pdbbase' got '%s'", arg);
|
||||
showError(filename, lineno, "Expecting 'pdbbase' got '%s'", arg);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
showError (filename, lineno, "Illegal argument type %d", piocshArg->type);
|
||||
showError(filename, lineno, "Illegal argument type %d",
|
||||
piocshArg->type);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -329,6 +337,7 @@ openRedirect(const char *filename, int lineno, struct iocshRedirect *redirect)
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
redirect->mustRestore = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -349,14 +358,17 @@ startRedirect(const char * /*filename*/, int /*lineno*/,
|
||||
case 0:
|
||||
redirect->oldFp = epicsGetThreadStdin();
|
||||
epicsSetThreadStdin(redirect->fp);
|
||||
redirect->mustRestore = 1;
|
||||
break;
|
||||
case 1:
|
||||
redirect->oldFp = epicsGetThreadStdout();
|
||||
epicsSetThreadStdout(redirect->fp);
|
||||
redirect->mustRestore = 1;
|
||||
break;
|
||||
case 2:
|
||||
redirect->oldFp = epicsGetThreadStderr();
|
||||
epicsSetThreadStderr(redirect->fp);
|
||||
redirect->mustRestore = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -377,10 +389,12 @@ stopRedirect(const char *filename, int lineno, struct iocshRedirect *redirect)
|
||||
showError(filename, lineno, "Error closing \"%s\": %s.",
|
||||
redirect->name, strerror(errno));
|
||||
redirect->fp = NULL;
|
||||
switch(i) {
|
||||
case 0: epicsSetThreadStdin(redirect->oldFp); break;
|
||||
case 1: epicsSetThreadStdout(redirect->oldFp); break;
|
||||
case 2: epicsSetThreadStderr(redirect->oldFp); break;
|
||||
if (redirect->mustRestore) {
|
||||
switch(i) {
|
||||
case 0: epicsSetThreadStdin(redirect->oldFp); break;
|
||||
case 1: epicsSetThreadStdout(redirect->oldFp); break;
|
||||
case 2: epicsSetThreadStderr(redirect->oldFp); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
redirect->name = NULL;
|
||||
@@ -404,30 +418,31 @@ static void helpCallFunc(const iocshArgBuf *args)
|
||||
if (argc == 1) {
|
||||
int l, col = 0;
|
||||
|
||||
printf ("Type 'help command_name' to get more information about a particular command.\n");
|
||||
fprintf(epicsGetStdout(),
|
||||
"Type 'help <command>' to see the arguments of <command>.\n");
|
||||
iocshTableLock ();
|
||||
for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) {
|
||||
piocshFuncDef = pcmd->pFuncDef;
|
||||
l = strlen (piocshFuncDef->name);
|
||||
if ((l + col) >= 79) {
|
||||
fputc ('\n', stdout);
|
||||
fputc('\n', epicsGetStdout());
|
||||
col = 0;
|
||||
}
|
||||
fputs (piocshFuncDef->name, stdout);
|
||||
fputs(piocshFuncDef->name, epicsGetStdout());
|
||||
col += l;
|
||||
if (col >= 64) {
|
||||
fputc ('\n', stdout);
|
||||
fputc('\n', epicsGetStdout());
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
do {
|
||||
fputc (' ', stdout);
|
||||
fputc(' ', epicsGetStdout());
|
||||
col++;
|
||||
} while ((col % 16) != 0);
|
||||
}
|
||||
}
|
||||
if (col)
|
||||
fputc ('\n', stdout);
|
||||
fputc('\n', epicsGetStdout());
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
else {
|
||||
@@ -435,18 +450,18 @@ static void helpCallFunc(const iocshArgBuf *args)
|
||||
for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) {
|
||||
piocshFuncDef = pcmd->pFuncDef;
|
||||
if (epicsStrGlobMatch(piocshFuncDef->name, argv[iarg]) != 0) {
|
||||
fputs (piocshFuncDef->name, stdout);
|
||||
fputs(piocshFuncDef->name, epicsGetStdout());
|
||||
for (int a = 0 ; a < piocshFuncDef->nargs ; a++) {
|
||||
const char *cp = piocshFuncDef->arg[a]->name;
|
||||
if ((piocshFuncDef->arg[a]->type == iocshArgArgv)
|
||||
|| (strchr (cp, ' ') == NULL)) {
|
||||
fprintf (stdout, " %s", cp);
|
||||
fprintf(epicsGetStdout(), " %s", cp);
|
||||
}
|
||||
else {
|
||||
fprintf (stdout, " '%s'", cp);
|
||||
fprintf(epicsGetStdout(), " '%s'", cp);
|
||||
}
|
||||
}
|
||||
fprintf (stdout,"\n");;
|
||||
fprintf(epicsGetStdout(),"\n");;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -478,7 +493,6 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
iocshArgBuf *argBuf = NULL;
|
||||
int argBufCapacity = 0;
|
||||
struct iocshCommand *found;
|
||||
struct iocshFuncDef const *piocshFuncDef;
|
||||
void *readlineContext = NULL;
|
||||
int wasOkToBlock;
|
||||
|
||||
@@ -493,7 +507,8 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
else {
|
||||
fp = fopen (pathname, "r");
|
||||
if (fp == NULL) {
|
||||
fprintf (stderr, "Can't open %s: %s\n", pathname, strerror (errno));
|
||||
fprintf(epicsGetStderr(), "Can't open %s: %s\n", pathname,
|
||||
strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
if ((filename = strrchr (pathname, '/')) == NULL)
|
||||
@@ -507,7 +522,7 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
* Create a command-line input context
|
||||
*/
|
||||
if ((readlineContext = epicsReadlineBegin(fp)) == NULL) {
|
||||
fprintf(stderr, "Can't allocate command-line object.\n");
|
||||
fprintf(epicsGetStderr(), "Can't allocate command-line object.\n");
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return -1;
|
||||
@@ -519,7 +534,7 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
*/
|
||||
redirects = (struct iocshRedirect *)calloc(NREDIRECTS, sizeof *redirects);
|
||||
if (redirects == NULL) {
|
||||
printf ("Out of memory!\n");
|
||||
fprintf(epicsGetStderr(), "Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -604,7 +619,7 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
argvCapacity += 50;
|
||||
av = (char **)realloc (argv, argvCapacity * sizeof *argv);
|
||||
if (av == NULL) {
|
||||
printf ("Out of memory!\n");
|
||||
fprintf (epicsGetStderr(), "Out of memory!\n");
|
||||
argc = -1;
|
||||
break;
|
||||
}
|
||||
@@ -699,17 +714,17 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
backslash = 0;
|
||||
}
|
||||
if (redirect != NULL) {
|
||||
showError (filename, lineno, "Illegal redirection.");
|
||||
showError(filename, lineno, "Illegal redirection.");
|
||||
continue;
|
||||
}
|
||||
if (argc < 0)
|
||||
break;
|
||||
if (quote != EOF) {
|
||||
showError (filename, lineno, "Unbalanced quote.");
|
||||
showError(filename, lineno, "Unbalanced quote.");
|
||||
continue;
|
||||
}
|
||||
if (backslash) {
|
||||
showError (filename, lineno, "Trailing backslash.");
|
||||
showError(filename, lineno, "Trailing backslash.");
|
||||
continue;
|
||||
}
|
||||
if (inword)
|
||||
@@ -730,73 +745,68 @@ iocshBody (const char *pathname, const char *commandLine)
|
||||
stopRedirect(filename, lineno, redirects);
|
||||
continue;
|
||||
}
|
||||
if (openRedirect(filename, lineno, redirects) < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Look up command
|
||||
* Special command?
|
||||
*/
|
||||
if (argc) {
|
||||
/*
|
||||
* Special command?
|
||||
*/
|
||||
if (strncmp (argv[0], "exit", 4) == 0)
|
||||
break;
|
||||
if ((strcmp (argv[0], "?") == 0)
|
||||
|| (strncmp (argv[0], "help", 4) == 0)) {
|
||||
}
|
||||
if ((argc > 0) && (strcmp(argv[0], "exit") == 0))
|
||||
break;
|
||||
|
||||
/*
|
||||
* Set up redirection
|
||||
*/
|
||||
if ((openRedirect(filename, lineno, redirects) == 0) && (argc > 0)) {
|
||||
/*
|
||||
* Look up command
|
||||
*/
|
||||
found = (iocshCommand *)registryFind (iocshCmdID, argv[0]);
|
||||
if (!found) {
|
||||
showError (filename, lineno, "Command %s not found.", argv[0]);
|
||||
continue;
|
||||
}
|
||||
piocshFuncDef = found->pFuncDef;
|
||||
|
||||
/*
|
||||
* Process arguments and call function
|
||||
*/
|
||||
for (int iarg = 0 ; ; ) {
|
||||
if (iarg == piocshFuncDef->nargs) {
|
||||
startRedirect(filename, lineno, redirects);
|
||||
(*found->func)(argBuf);
|
||||
stopRedirect(filename, lineno, redirects);
|
||||
break;
|
||||
}
|
||||
if (iarg >= argBufCapacity) {
|
||||
void *np;
|
||||
|
||||
argBufCapacity += 20;
|
||||
np = realloc (argBuf, argBufCapacity * sizeof *argBuf);
|
||||
if (np == NULL) {
|
||||
fprintf (stderr, "Out of memory!\n");
|
||||
argBufCapacity -= 20;
|
||||
if (found) {
|
||||
/*
|
||||
* Process arguments and call function
|
||||
*/
|
||||
struct iocshFuncDef const *piocshFuncDef = found->pFuncDef;
|
||||
for (int iarg = 0 ; ; ) {
|
||||
if (iarg == piocshFuncDef->nargs) {
|
||||
startRedirect(filename, lineno, redirects);
|
||||
(*found->func)(argBuf);
|
||||
break;
|
||||
}
|
||||
argBuf = (iocshArgBuf *)np;
|
||||
if (iarg >= argBufCapacity) {
|
||||
void *np;
|
||||
|
||||
argBufCapacity += 20;
|
||||
np = realloc (argBuf, argBufCapacity * sizeof *argBuf);
|
||||
if (np == NULL) {
|
||||
fprintf (epicsGetStderr(), "Out of memory!\n");
|
||||
argBufCapacity -= 20;
|
||||
break;
|
||||
}
|
||||
argBuf = (iocshArgBuf *)np;
|
||||
}
|
||||
if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) {
|
||||
argBuf[iarg].aval.ac = argc-iarg;
|
||||
argBuf[iarg].aval.av = argv+iarg;
|
||||
iarg = piocshFuncDef->nargs;
|
||||
}
|
||||
else {
|
||||
if (!cvtArg (filename, lineno,
|
||||
((iarg < argc) ? argv[iarg+1] : NULL),
|
||||
&argBuf[iarg], piocshFuncDef->arg[iarg]))
|
||||
break;
|
||||
iarg++;
|
||||
}
|
||||
}
|
||||
if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) {
|
||||
argBuf[iarg].aval.ac = argc-iarg;
|
||||
argBuf[iarg].aval.av = argv+iarg;
|
||||
iarg = piocshFuncDef->nargs;
|
||||
}
|
||||
else {
|
||||
if (!cvtArg (filename, lineno,
|
||||
((iarg < argc) ? argv[iarg+1] : NULL),
|
||||
&argBuf[iarg], piocshFuncDef->arg[iarg]))
|
||||
break;
|
||||
iarg++;
|
||||
if ((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) {
|
||||
const char *newPrompt;
|
||||
if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL)
|
||||
prompt = newPrompt;
|
||||
}
|
||||
}
|
||||
if((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) {
|
||||
const char *newPrompt;
|
||||
if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL)
|
||||
prompt = newPrompt;
|
||||
else {
|
||||
showError(filename, lineno, "Command %s not found.", argv[0]);
|
||||
}
|
||||
}
|
||||
stopRedirect(filename, lineno, redirects);
|
||||
}
|
||||
if (fp && (fp != stdin))
|
||||
fclose (fp);
|
||||
@@ -840,7 +850,8 @@ static void varHandler(const iocshVarDef *v, const char *setString)
|
||||
{
|
||||
switch(v->type) {
|
||||
default:
|
||||
printf("Can't handle variable %s of type %d.\n", v->name, v->type);
|
||||
fprintf(epicsGetStderr(), "Can't handle variable %s of type %d.\n",
|
||||
v->name, v->type);
|
||||
return;
|
||||
case iocshArgInt: break;
|
||||
case iocshArgDouble: break;
|
||||
@@ -849,10 +860,10 @@ static void varHandler(const iocshVarDef *v, const char *setString)
|
||||
switch(v->type) {
|
||||
default: break;
|
||||
case iocshArgInt:
|
||||
printf("%s = %d\n", v->name, *(int *)v->pval);
|
||||
fprintf(epicsGetStdout(), "%s = %d\n", v->name, *(int *)v->pval);
|
||||
break;
|
||||
case iocshArgDouble:
|
||||
printf("%s = %g\n", v->name, *(double *)v->pval);
|
||||
fprintf(epicsGetStdout(), "%s = %g\n", v->name, *(double *)v->pval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -866,7 +877,8 @@ static void varHandler(const iocshVarDef *v, const char *setString)
|
||||
if((*setString != '\0') && (*endp == '\0'))
|
||||
*(int *)v->pval = ltmp;
|
||||
else
|
||||
printf("Invalid value -- value of %s not changed.\n", v->name);
|
||||
fprintf(epicsGetStderr(),
|
||||
"Invalid integer value. Var %s not changed.\n", v->name);
|
||||
break;
|
||||
}
|
||||
case iocshArgDouble:
|
||||
@@ -876,7 +888,8 @@ static void varHandler(const iocshVarDef *v, const char *setString)
|
||||
if((*setString != '\0') && (*endp == '\0'))
|
||||
*(double *)v->pval = dtmp;
|
||||
else
|
||||
printf("Invalid value -- value of %s not changed.\n", v->name);
|
||||
fprintf(epicsGetStderr(),
|
||||
"Invalid double value. Var %s not changed.\n", v->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -893,7 +906,7 @@ static void varCallFunc(const iocshArgBuf *args)
|
||||
else {
|
||||
v = (iocshVariable *)registryFind(iocshVarID, args[0].sval);
|
||||
if (v == NULL) {
|
||||
printf("%s -- no such variable.\n", args[0].sval);
|
||||
fprintf(epicsGetStderr(), "Var %s not found.\n", args[0].sval);
|
||||
}
|
||||
else {
|
||||
varHandler(v->pVarDef, args[1].sval);
|
||||
@@ -916,7 +929,8 @@ static void iocshCmdCallFunc(const iocshArgBuf *args)
|
||||
*/
|
||||
|
||||
/* comment */
|
||||
static const iocshArg commentArg0 = { "newline-terminated comment",iocshArgArgv};
|
||||
static const iocshArg commentArg0 = { "newline-terminated comment",
|
||||
iocshArgArgv};
|
||||
static const iocshArg *commentArgs[1] = {&commentArg0};
|
||||
static const iocshFuncDef commentFuncDef = {"#",1,commentArgs};
|
||||
static void commentCallFunc(const iocshArgBuf *)
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
\*************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "iocsh.h"
|
||||
#include "epicsStdioRedirect.h"
|
||||
#include "epicsTime.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsMutex.h"
|
||||
@@ -60,7 +60,7 @@ static void chdirCallFunc(const iocshArgBuf *args)
|
||||
int status;
|
||||
status = chdir(args[0].sval);
|
||||
if (status) {
|
||||
printf ("Invalid directory path ignored\n");
|
||||
fprintf(stderr, "Invalid directory path, ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +86,11 @@ static void epicsEnvSetCallFunc(const iocshArgBuf *args)
|
||||
char *value = args[1].sval;
|
||||
|
||||
if (name == NULL) {
|
||||
printf ("Missing environment variable name argument.\n");
|
||||
fprintf(stderr, "Missing environment variable name argument.\n");
|
||||
return;
|
||||
}
|
||||
if (value == NULL) {
|
||||
printf ("Missing environment variable value argument.\n");
|
||||
fprintf(stderr, "Missing environment variable value argument.\n");
|
||||
return;
|
||||
}
|
||||
epicsEnvSet (name, value);
|
||||
@@ -231,7 +231,7 @@ static void threadCallFunc(const iocshArgBuf *args)
|
||||
if (*endp) {
|
||||
tid = epicsThreadGetId (cp);
|
||||
if (!tid) {
|
||||
printf ("\t'%s' is not a known thread name\n", cp);
|
||||
fprintf(stderr, "\t'%s' is not a known thread name\n", cp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -299,7 +299,7 @@ static void epicsThreadResumeCallFunc(const iocshArgBuf *args)
|
||||
if (*endp) {
|
||||
tid = epicsThreadGetId(cp);
|
||||
if (!tid) {
|
||||
printf("*** argument %d (%s) is not a valid thread name ***\n", i, cp);
|
||||
fprintf(stderr, "'%s' is not a valid thread name\n", cp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -307,13 +307,13 @@ static void epicsThreadResumeCallFunc(const iocshArgBuf *args)
|
||||
tid =(epicsThreadId)ltmp;
|
||||
epicsThreadGetName(tid, nameBuf, sizeof nameBuf);
|
||||
if (nameBuf[0] == '\0') {
|
||||
printf("*** argument %d (%s) is not a valid thread id ***\n", i, cp);
|
||||
fprintf(stderr, "'%s' is not a valid thread id\n", cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!epicsThreadIsSuspended(tid)) {
|
||||
printf("*** Thread %s is not suspended ***\n", cp);
|
||||
fprintf(stderr, "Thread %s is not suspended\n", cp);
|
||||
continue;
|
||||
}
|
||||
epicsThreadResume(tid);
|
||||
|
||||
@@ -83,7 +83,7 @@ static void epicsExitCallAtExitsPvt ( exitPvt * pep )
|
||||
}
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsExitCallAtExits ( void )
|
||||
epicsShareFunc void epicsExitCallAtExits ( void )
|
||||
{
|
||||
exitPvt * pep = 0;
|
||||
epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 );
|
||||
@@ -99,7 +99,7 @@ epicsShareFunc void epicsShareAPI epicsExitCallAtExits ( void )
|
||||
}
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsExitCallAtThreadExits ( void )
|
||||
epicsShareFunc void epicsExitCallAtThreadExits ( void )
|
||||
{
|
||||
exitPvt * pep;
|
||||
epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 );
|
||||
@@ -126,7 +126,7 @@ static int epicsAtExitPvt (
|
||||
return status;
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI epicsAtThreadExit (
|
||||
epicsShareFunc int epicsAtThreadExit (
|
||||
epicsExitFunc func, void *arg )
|
||||
{
|
||||
exitPvt * pep;
|
||||
@@ -142,7 +142,7 @@ epicsShareFunc int epicsShareAPI epicsAtThreadExit (
|
||||
return epicsAtExitPvt ( pep, func, arg );
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI epicsAtExit(
|
||||
epicsShareFunc int epicsAtExit(
|
||||
epicsExitFunc func, void *arg )
|
||||
{
|
||||
int status = -1;
|
||||
@@ -155,7 +155,7 @@ epicsShareFunc int epicsShareAPI epicsAtExit(
|
||||
return status;
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsExit(int status)
|
||||
epicsShareFunc void epicsExit(int status)
|
||||
{
|
||||
epicsExitCallAtExits();
|
||||
epicsThreadSleep(1.0);
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsExit(int status);
|
||||
epicsShareFunc void epicsShareAPI epicsExitCallAtExits(void);
|
||||
epicsShareFunc int epicsShareAPI epicsAtExit(
|
||||
void (*epicsExitFunc)(void *arg),void *arg);
|
||||
epicsShareFunc void epicsExit(int status);
|
||||
epicsShareFunc void epicsExitCallAtExits(void);
|
||||
epicsShareFunc int epicsAtExit(void (*epicsExitFunc)(void *arg),void *arg);
|
||||
|
||||
epicsShareFunc void epicsShareAPI epicsExitCallAtThreadExits(void);
|
||||
epicsShareFunc int epicsShareAPI epicsAtThreadExit(
|
||||
epicsShareFunc void epicsExitCallAtThreadExits(void);
|
||||
epicsShareFunc int epicsAtThreadExit(
|
||||
void (*epicsExitFunc)(void *arg),void *arg);
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
/* Original Authors: David H. Thompson & Sheng Peng (ORNL) */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -19,6 +18,7 @@
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsMessageQueue.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsStdioRedirect.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsTime.h"
|
||||
#include "epicsTimer.h"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "dbDefs.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsExit.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsStdioRedirect.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "errlog.h"
|
||||
|
||||
@@ -37,6 +37,11 @@ epicsEllTest_SRCS += epicsEllTest.c
|
||||
testHarness_SRCS += epicsEllTest.c
|
||||
TESTS += epicsEllTest
|
||||
|
||||
TESTPROD_HOST += epicsEnvTest
|
||||
epicsEnvTest_SRCS += epicsEnvTest.c
|
||||
testHarness_SRCS += epicsEnvTest.c
|
||||
TESTS += epicsEnvTest
|
||||
|
||||
TESTPROD_HOST += epicsErrlogTest
|
||||
epicsErrlogTest_SRCS += epicsErrlogTest.c
|
||||
testHarness_SRCS += epicsErrlogTest.c
|
||||
|
||||
78
src/libCom/test/epicsEnvTest.c
Normal file
78
src/libCom/test/epicsEnvTest.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* epicsEnvTest.c */
|
||||
|
||||
/* Author: Andrew Johnson
|
||||
* Date: 2013-12-13
|
||||
*/
|
||||
|
||||
/* Check environment variable APIs.
|
||||
* TODO: Add tests for envDefs.h routines.
|
||||
*
|
||||
* The thread test is needed on VxWorks 6.x, where the OS can be
|
||||
* configured to maintain separate, totally independent sets
|
||||
* of environment variables for each thread. This configuration
|
||||
* is not supported by EPICS which expects child threads to at
|
||||
* least inherit the partent thread's environment variables.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "envDefs.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsUnitTest.h"
|
||||
#include "testMain.h"
|
||||
|
||||
#define PARENT "Parent"
|
||||
#define CHILD "Child"
|
||||
|
||||
static void child(void *arg)
|
||||
{
|
||||
const char *value = getenv(PARENT);
|
||||
|
||||
if (!testOk(value && (strcmp(value, PARENT) == 0),
|
||||
"Child thread sees parent environment values")) {
|
||||
#ifdef vxWorks
|
||||
testDiag("VxWorks image needs ENV_VAR_USE_HOOKS configured as FALSE");
|
||||
#else
|
||||
testDiag("Check OS configuration, environment inheritance needed");
|
||||
#endif
|
||||
}
|
||||
|
||||
epicsEnvSet(CHILD, CHILD);
|
||||
}
|
||||
|
||||
MAIN(epicsEnvTest)
|
||||
{
|
||||
unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall);
|
||||
const char *value;
|
||||
|
||||
testPlan(3);
|
||||
|
||||
epicsEnvSet(PARENT, PARENT);
|
||||
|
||||
value = getenv(PARENT);
|
||||
if (!testOk(value && (strcmp(value, PARENT) == 0),
|
||||
"epicsEnvSet correctly modifies environment"))
|
||||
testAbort("environment variables not working");
|
||||
|
||||
epicsThreadCreate("child", 50, stackSize, child, NULL);
|
||||
epicsThreadSleep(0.1);
|
||||
|
||||
value = getenv(CHILD);
|
||||
if (value && (strcmp(value, CHILD) == 0))
|
||||
testDiag("Child and parent threads share a common environment");
|
||||
|
||||
value = getenv(PARENT);
|
||||
testOk(value && (strcmp(value, PARENT) == 0),
|
||||
"PARENT environment variable not modified");
|
||||
|
||||
testDone();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ int epicsThreadTest(void);
|
||||
int epicsTimerTest(void);
|
||||
int epicsAlgorithm(void);
|
||||
int epicsEllTest(void);
|
||||
int epicsEnvTest(void);
|
||||
int epicsErrlogTest(void);
|
||||
int epicsCalcTest(void);
|
||||
int epicsEventTest(void);
|
||||
@@ -60,6 +61,8 @@ void epicsRunLibComTests(void)
|
||||
|
||||
runTest(epicsEllTest);
|
||||
|
||||
runTest(epicsEnvTest);
|
||||
|
||||
runTest(epicsErrlogTest);
|
||||
|
||||
runTest(epicsCalcTest);
|
||||
|
||||
@@ -31,7 +31,10 @@ sub GetEpicsHostArch { # no args
|
||||
} elsif ($arch =~ m/arm-linux/) { return "linux-arm";
|
||||
} elsif ($arch =~ m/MSWin32-x86/) { return "win32-x86";
|
||||
} elsif ($arch =~ m/MSWin32-x64/) { return "windows-x64";
|
||||
} elsif ($arch =~ m/cygwin/) { return "cygwin-x86";
|
||||
} elsif ($arch =~ m/cygwin/) {
|
||||
my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname();
|
||||
if ($cpu =~ m/x86_64/) { return "cygwin-x86_64"; }
|
||||
return "cygwin-x86";
|
||||
} elsif ($arch =~ m/darwin/) {
|
||||
my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname();
|
||||
if ($cpu =~ m/Power Macintosh/) { return "darwin-ppc"; }
|
||||
|
||||
Reference in New Issue
Block a user