Reorganized iocsh command registration to untangle the build order.
The iocsh core is now part of libCom, and commands are registered locally with a Register routine for each IOC library.
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
#*************************************************************************
|
||||
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
# Copyright (c) 2007 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
|
||||
# EPICS BASE is distributed subject to a Software License Agreement found
|
||||
# in file LICENSE that is included with this distribution.
|
||||
#*************************************************************************
|
||||
TOP = ../..
|
||||
@@ -103,6 +102,14 @@ INC += gpHash.h
|
||||
SRCS += gpHashLib.c
|
||||
HTMLS += gpHash/gpHash.html
|
||||
|
||||
SRC_DIRS += $(LIBCOM)/iocsh
|
||||
INC += iocsh.h
|
||||
INC += registry.h
|
||||
INC += libComRegister.h
|
||||
SRCS += iocsh.cpp
|
||||
SRCS += registry.c
|
||||
SRCS += libComRegister.c
|
||||
|
||||
SRC_DIRS += $(LIBCOM)/logClient
|
||||
INC += iocLog.h
|
||||
INC += logClient.h
|
||||
@@ -235,12 +242,13 @@ SRC_DIRS += $(LIBCOM)/tsDefs
|
||||
INC += tsDefs.h
|
||||
SRCS += tsDefs.c
|
||||
|
||||
# For vxWorks a clock
|
||||
# These files are in osi/os/vxWorks
|
||||
# IOC Time of Day clock
|
||||
INC_vxWorks += iocClock.h
|
||||
SRCS_vxWorks += iocClock.c
|
||||
#For vxWorks special reboot hook
|
||||
# Special reboot hook
|
||||
SRCS_vxWorks += atReboot.cpp
|
||||
#For old vxWorks applications
|
||||
# For old vxWorks applications
|
||||
INC_vxWorks += camacLib.h
|
||||
INC_vxWorks += epicsDynLink.h
|
||||
INC_vxWorks += module_types.h
|
||||
@@ -252,6 +260,7 @@ SRCS_vxWorks += logMsgToErrlog.cpp
|
||||
#This forces the vxWorks compatibility stuff to be loaded
|
||||
OBJS_vxWorks = vxComLibrary
|
||||
|
||||
# These files are in osi/os/WIN32
|
||||
SRCS_WIN32 += epicsGetopt.c
|
||||
SRCS_WIN32 += setThreadName.cpp
|
||||
#SRCS_WIN32 += dllmain.cpp
|
||||
@@ -276,12 +285,6 @@ endif
|
||||
PROD_LIBS = Com
|
||||
PROD_SYS_LIBS_WIN32 = ws2_32 advapi32
|
||||
|
||||
#USR_CFLAGS += -DTS_TEST
|
||||
#TESTPROD_SRCS=tsSubr.c
|
||||
#TESTPROD_HOST=testtsLib
|
||||
#TESTPROD_HOST=envtest
|
||||
#TESTPROD_HOST=osiTimeTest fdManagerTest
|
||||
|
||||
# for bldErrSymTbl:
|
||||
#
|
||||
ERR_S_FILES += $(TOP)/src/libCom/osi/devLib.h
|
||||
|
||||
925
src/libCom/iocsh/iocsh.cpp
Normal file
925
src/libCom/iocsh/iocsh.cpp
Normal file
@@ -0,0 +1,925 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, 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.
|
||||
\*************************************************************************/
|
||||
/* iocsh.cpp */
|
||||
/* Author: Marty Kraimer Date: 27APR2000 */
|
||||
/* Heavily modified by Eric Norum Date: 03MAY2000 */
|
||||
/* Adapted to C++ by Eric Norum Date: 18DEC2000 */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "errlog.h"
|
||||
#include "macLib.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsString.h"
|
||||
#include "epicsStdlib.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "envDefs.h"
|
||||
#include "registry.h"
|
||||
#include "epicsReadline.h"
|
||||
#include "cantProceed.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "iocsh.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
* Global link to pdbbase
|
||||
*/
|
||||
epicsShareDef struct dbBase **iocshPpdbbase;
|
||||
|
||||
/*
|
||||
* File-local information
|
||||
*/
|
||||
struct iocshCommand {
|
||||
iocshFuncDef const *pFuncDef;
|
||||
iocshCallFunc func;
|
||||
struct iocshCommand *next;
|
||||
};
|
||||
static struct iocshCommand *iocshCommandHead;
|
||||
static char iocshCmdID[] = "iocshCmd";
|
||||
struct iocshVariable {
|
||||
iocshVarDef const *pVarDef;
|
||||
struct iocshVariable *next;
|
||||
};
|
||||
static struct iocshVariable *iocshVariableHead;
|
||||
static char iocshVarID[] = "iocshVar";
|
||||
extern "C" { static void varCallFunc(const iocshArgBuf *); }
|
||||
static epicsMutexId iocshTableMutex;
|
||||
static epicsThreadOnceId iocshTableOnceId = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
/*
|
||||
* I/O redirection
|
||||
*/
|
||||
#define NREDIRECTS 5
|
||||
struct iocshRedirect {
|
||||
const char *name;
|
||||
const char *mode;
|
||||
FILE *fp;
|
||||
FILE *oldFp;
|
||||
};
|
||||
|
||||
/*
|
||||
* Set up command table mutex
|
||||
*/
|
||||
static void iocshTableOnce (void *)
|
||||
{
|
||||
iocshTableMutex = epicsMutexMustCreate ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the table mutex
|
||||
*/
|
||||
static void
|
||||
iocshTableLock (void)
|
||||
{
|
||||
epicsThreadOnce (&iocshTableOnceId, iocshTableOnce, NULL);
|
||||
epicsMutexMustLock (iocshTableMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlock the table mutex
|
||||
*/
|
||||
static void
|
||||
iocshTableUnlock (void)
|
||||
{
|
||||
epicsThreadOnce (&iocshTableOnceId, iocshTableOnce, NULL);
|
||||
epicsMutexUnlock (iocshTableMutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a command
|
||||
*/
|
||||
void epicsShareAPI iocshRegister (const iocshFuncDef *piocshFuncDef, iocshCallFunc func)
|
||||
{
|
||||
struct iocshCommand *l, *p, *n;
|
||||
int i;
|
||||
|
||||
iocshTableLock ();
|
||||
for (l = NULL, p = iocshCommandHead ; p != NULL ; l = p, p = p->next) {
|
||||
i = strcmp (piocshFuncDef->name, p->pFuncDef->name);
|
||||
if (i == 0) {
|
||||
p->pFuncDef = piocshFuncDef;
|
||||
p->func = func;
|
||||
iocshTableUnlock ();
|
||||
return;
|
||||
}
|
||||
if (i < 0)
|
||||
break;
|
||||
}
|
||||
n = (struct iocshCommand *)callocMustSucceed (1, sizeof *n, "iocshRegister");
|
||||
if (!registryAdd(iocshCmdID, piocshFuncDef->name, (void *)n)) {
|
||||
free (n);
|
||||
iocshTableUnlock ();
|
||||
errlogPrintf ("iocshRegister failed to add %s\n", piocshFuncDef->name);
|
||||
return;
|
||||
}
|
||||
if (l == NULL) {
|
||||
n->next = iocshCommandHead;
|
||||
iocshCommandHead = n;
|
||||
}
|
||||
else {
|
||||
n->next = l->next;
|
||||
l->next = n;
|
||||
}
|
||||
n->pFuncDef = piocshFuncDef;
|
||||
n->func = func;
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Register variable(s)
|
||||
*/
|
||||
void epicsShareAPI iocshRegisterVariable (const iocshVarDef *piocshVarDef)
|
||||
{
|
||||
struct iocshVariable *l, *p, *n;
|
||||
int i;
|
||||
int found;
|
||||
static const iocshArg varArg0 = { "[variable",iocshArgString};
|
||||
static const iocshArg varArg1 = { "[value]]",iocshArgString};
|
||||
static const iocshArg *varArgs[2] = {&varArg0, &varArg1};
|
||||
static const iocshFuncDef varFuncDef = {"var",2,varArgs};
|
||||
|
||||
iocshTableLock ();
|
||||
while ((piocshVarDef != NULL)
|
||||
&& (piocshVarDef->name != NULL)
|
||||
&& (*piocshVarDef->name != '\0')) {
|
||||
if (iocshVariableHead == NULL)
|
||||
iocshRegister(&varFuncDef,varCallFunc);
|
||||
found = 0;
|
||||
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);
|
||||
p->pVarDef = piocshVarDef;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
if (l == NULL) {
|
||||
n->next = iocshVariableHead;
|
||||
iocshVariableHead = n;
|
||||
}
|
||||
else {
|
||||
n->next = l->next;
|
||||
l->next = n;
|
||||
}
|
||||
n->pVarDef = piocshVarDef;
|
||||
}
|
||||
piocshVarDef++;
|
||||
}
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Free storage created by iocshRegister/iocshRegisterVariable
|
||||
*/
|
||||
void epicsShareAPI iocshFree(void)
|
||||
{
|
||||
struct iocshCommand *pc, *nc;
|
||||
struct iocshVariable *pv, *nv;
|
||||
|
||||
iocshTableLock ();
|
||||
for (pc = iocshCommandHead ; pc != NULL ; ) {
|
||||
nc = pc->next;
|
||||
free (pc);
|
||||
pc = nc;
|
||||
}
|
||||
for (pv = iocshVariableHead ; pv != NULL ; ) {
|
||||
nv = pv->next;
|
||||
free (pv);
|
||||
pv = nv;
|
||||
}
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Report an error
|
||||
*/
|
||||
static void
|
||||
showError (const char *filename, int lineno, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, msg);
|
||||
if (filename)
|
||||
fprintf (stderr, "%s -- Line %d -- ", filename, lineno);
|
||||
vfprintf (stderr, msg, ap);
|
||||
fputc ('\n', stderr);
|
||||
va_end (ap);
|
||||
}
|
||||
|
||||
static int
|
||||
cvtArg (const char *filename, int lineno, char *arg, iocshArgBuf *argBuf, const iocshArg *piocshArg)
|
||||
{
|
||||
char *endp;
|
||||
|
||||
switch (piocshArg->type) {
|
||||
case iocshArgInt:
|
||||
if (arg && *arg) {
|
||||
errno = 0;
|
||||
argBuf->ival = strtol (arg, &endp, 0);
|
||||
if (errno == ERANGE) {
|
||||
errno = 0;
|
||||
argBuf->ival = strtoul (arg, &endp, 0);
|
||||
if (errno == ERANGE) {
|
||||
showError (filename, lineno, "Integer `%s' out of range", arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (*endp) {
|
||||
showError (filename, lineno, "Illegal integer `%s'", arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
argBuf->ival = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case iocshArgDouble:
|
||||
if (arg && *arg) {
|
||||
argBuf->dval = epicsStrtod (arg, &endp);
|
||||
if (*endp) {
|
||||
showError (filename, lineno, "Illegal double `%s'", arg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
argBuf->dval = 0.0;
|
||||
}
|
||||
break;
|
||||
|
||||
case iocshArgString:
|
||||
argBuf->sval = arg;
|
||||
break;
|
||||
|
||||
case iocshArgPersistentString:
|
||||
argBuf->sval = epicsStrDup(arg);
|
||||
if (argBuf->sval == NULL) {
|
||||
showError (filename, lineno, "Out of memory");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case iocshArgPdbbase:
|
||||
/* 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");
|
||||
return 0;
|
||||
}
|
||||
argBuf->vval = *iocshPpdbbase;
|
||||
break;
|
||||
}
|
||||
showError (filename, lineno, "Expecting `pdbbase' got `%s'", arg);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
showError (filename, lineno, "Illegal argument type %d", piocshArg->type);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open redirected I/O
|
||||
*/
|
||||
static int
|
||||
openRedirect(const char *filename, int lineno, struct iocshRedirect *redirect)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < NREDIRECTS ; i++, redirect++) {
|
||||
if (redirect->name != NULL) {
|
||||
redirect->fp = fopen(redirect->name, redirect->mode);
|
||||
if (redirect->fp == NULL) {
|
||||
showError(filename, lineno, "Can't open \"%s\": %s.",
|
||||
redirect->name, strerror(errno));
|
||||
redirect->name = NULL;
|
||||
while (i--) {
|
||||
redirect--;
|
||||
if (redirect->fp) {
|
||||
fclose(redirect->fp);
|
||||
redirect->fp = NULL;
|
||||
}
|
||||
redirect->name = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start I/O redirection
|
||||
*/
|
||||
static void
|
||||
startRedirect(const char * /*filename*/, int /*lineno*/,
|
||||
struct iocshRedirect *redirect)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < NREDIRECTS ; i++, redirect++) {
|
||||
if (redirect->fp != NULL) {
|
||||
switch(i) {
|
||||
case 0:
|
||||
redirect->oldFp = epicsGetThreadStdin();
|
||||
epicsSetThreadStdin(redirect->fp);
|
||||
break;
|
||||
case 1:
|
||||
redirect->oldFp = epicsGetThreadStdout();
|
||||
epicsSetThreadStdout(redirect->fp);
|
||||
break;
|
||||
case 2:
|
||||
redirect->oldFp = epicsGetThreadStderr();
|
||||
epicsSetThreadStderr(redirect->fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish up I/O redirection
|
||||
*/
|
||||
static void
|
||||
stopRedirect(const char *filename, int lineno, struct iocshRedirect *redirect)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < NREDIRECTS ; i++, redirect++) {
|
||||
if (redirect->fp != NULL) {
|
||||
if (fclose(redirect->fp) != 0)
|
||||
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;
|
||||
}
|
||||
}
|
||||
redirect->name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* "help" command
|
||||
*/
|
||||
static const iocshArg helpArg0 = { "[command ...]",iocshArgArgv};
|
||||
static const iocshArg *helpArgs[1] = {&helpArg0};
|
||||
static const iocshFuncDef helpFuncDef =
|
||||
{"help",1,helpArgs};
|
||||
static void helpCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
int argc = args[0].aval.ac;
|
||||
const char * const * argv = args[0].aval.av;
|
||||
struct iocshFuncDef const *piocshFuncDef;
|
||||
struct iocshCommand *pcmd;
|
||||
|
||||
if (argc == 1) {
|
||||
int l, col = 0;
|
||||
|
||||
printf ("Type `help command_name' to get more information about a particular 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);
|
||||
col = 0;
|
||||
}
|
||||
fputs (piocshFuncDef->name, stdout);
|
||||
col += l;
|
||||
if (col >= 64) {
|
||||
fputc ('\n', stdout);
|
||||
col = 0;
|
||||
}
|
||||
else {
|
||||
do {
|
||||
fputc (' ', stdout);
|
||||
col++;
|
||||
} while ((col % 16) != 0);
|
||||
}
|
||||
}
|
||||
if (col)
|
||||
fputc ('\n', stdout);
|
||||
iocshTableUnlock ();
|
||||
}
|
||||
else {
|
||||
for (int iarg = 1 ; iarg < argc ; iarg++) {
|
||||
for (pcmd = iocshCommandHead ; pcmd != NULL ; pcmd = pcmd->next) {
|
||||
piocshFuncDef = pcmd->pFuncDef;
|
||||
if (epicsStrGlobMatch(piocshFuncDef->name, argv[iarg]) != 0) {
|
||||
fputs (piocshFuncDef->name, stdout);
|
||||
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);
|
||||
}
|
||||
else {
|
||||
fprintf (stdout, " '%s'", cp);
|
||||
}
|
||||
}
|
||||
fprintf (stdout,"\n");;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The body of the command interpreter
|
||||
*/
|
||||
static int
|
||||
iocshBody (const char *pathname, const char *commandLine)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
const char *filename = NULL;
|
||||
int icin, icout;
|
||||
char c;
|
||||
int quote, inword, backslash;
|
||||
const char *raw = NULL;;
|
||||
char *line = NULL;
|
||||
int lineno = 0;
|
||||
int argc;
|
||||
char **argv = NULL;
|
||||
int argvCapacity = 0;
|
||||
struct iocshRedirect *redirects = NULL;
|
||||
struct iocshRedirect *redirect = NULL;
|
||||
int sep;
|
||||
const char *prompt = NULL;
|
||||
const char *ifs = " \t(),\r";
|
||||
iocshArgBuf *argBuf = NULL;
|
||||
int argBufCapacity = 0;
|
||||
struct iocshCommand *found;
|
||||
struct iocshFuncDef const *piocshFuncDef;
|
||||
void *readlineContext = NULL;
|
||||
int wasOkToBlock;
|
||||
|
||||
/*
|
||||
* See if command interpreter is interactive
|
||||
*/
|
||||
if (commandLine == NULL) {
|
||||
if ((pathname == NULL) || (strcmp (pathname, "<telnet>") == 0)) {
|
||||
if ((prompt = envGetConfigParamPtr(&IOCSH_PS1)) == NULL)
|
||||
prompt = "epics> ";
|
||||
}
|
||||
else {
|
||||
fp = fopen (pathname, "r");
|
||||
if (fp == NULL) {
|
||||
fprintf (stderr, "Can't open %s: %s\n", pathname, strerror (errno));
|
||||
return -1;
|
||||
}
|
||||
if ((filename = strrchr (pathname, '/')) == NULL)
|
||||
filename = pathname;
|
||||
else
|
||||
filename++;
|
||||
prompt = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a command-line input context
|
||||
*/
|
||||
if ((readlineContext = epicsReadlineBegin(fp)) == NULL) {
|
||||
fprintf(stderr, "Can't allocate command-line object.\n");
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up redirection
|
||||
*/
|
||||
redirects = (struct iocshRedirect *)calloc(NREDIRECTS, sizeof *redirects);
|
||||
if (redirects == NULL) {
|
||||
printf ("Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read commands till EOF or exit
|
||||
*/
|
||||
argc = 0;
|
||||
wasOkToBlock = epicsThreadIsOkToBlock();
|
||||
epicsThreadSetOkToBlock(1);
|
||||
for (;;) {
|
||||
/*
|
||||
* Read a line
|
||||
*/
|
||||
if (commandLine) {
|
||||
if (raw != NULL)
|
||||
break;
|
||||
raw = commandLine;
|
||||
}
|
||||
else {
|
||||
if ((raw = epicsReadline(prompt, readlineContext)) == NULL)
|
||||
break;
|
||||
}
|
||||
lineno++;
|
||||
|
||||
/*
|
||||
* Ignore comment lines other than to echo
|
||||
* them if they came from a script.
|
||||
*/
|
||||
if (*raw == '#') {
|
||||
if ((prompt == NULL) && (commandLine == NULL))
|
||||
puts(raw);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand macros
|
||||
*/
|
||||
free(line);
|
||||
if ((line = macEnvExpand(raw)) == NULL)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Echo commands read from scripts
|
||||
*/
|
||||
if ((prompt == NULL) && *line && (commandLine == NULL))
|
||||
puts(line);
|
||||
|
||||
/*
|
||||
* Break line into words
|
||||
*/
|
||||
icout = icin = 0;
|
||||
inword = 0;
|
||||
argc = 0;
|
||||
quote = EOF;
|
||||
backslash = 0;
|
||||
redirect = NULL;
|
||||
for (;;) {
|
||||
if (argc >= argvCapacity) {
|
||||
char **av;
|
||||
argvCapacity += 50;
|
||||
av = (char **)realloc (argv, argvCapacity * sizeof *argv);
|
||||
if (av == NULL) {
|
||||
printf ("Out of memory!\n");
|
||||
argc = -1;
|
||||
break;
|
||||
}
|
||||
argv = av;
|
||||
}
|
||||
c = line[icin++];
|
||||
if (c == '\0')
|
||||
break;
|
||||
if ((quote == EOF) && !backslash && (strchr (ifs, c)))
|
||||
sep = 1;
|
||||
else
|
||||
sep = 0;
|
||||
if ((quote == EOF) && !backslash) {
|
||||
int redirectFd = 1;
|
||||
if (c == '\\') {
|
||||
backslash = 1;
|
||||
continue;
|
||||
}
|
||||
if (c == '<') {
|
||||
if (redirect != NULL) {
|
||||
break;
|
||||
}
|
||||
redirect = &redirects[0];
|
||||
sep = 1;
|
||||
redirect->mode = "r";
|
||||
}
|
||||
if ((c >= '1') && (c <= '9') && (line[icin] == '>')) {
|
||||
redirectFd = c - '0';
|
||||
c = '>';
|
||||
icin++;
|
||||
}
|
||||
if (c == '>') {
|
||||
if (redirect != NULL)
|
||||
break;
|
||||
if (redirectFd >= NREDIRECTS) {
|
||||
redirect = &redirects[1];
|
||||
break;
|
||||
}
|
||||
redirect = &redirects[redirectFd];
|
||||
sep = 1;
|
||||
if (line[icin] == '>') {
|
||||
icin++;
|
||||
redirect->mode = "a";
|
||||
}
|
||||
else {
|
||||
redirect->mode = "w";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inword) {
|
||||
if (c == quote) {
|
||||
quote = EOF;
|
||||
}
|
||||
else {
|
||||
if ((quote == EOF) && !backslash) {
|
||||
if (sep) {
|
||||
inword = 0;
|
||||
line[icout++] = '\0';
|
||||
}
|
||||
else if ((c == '"') || (c == '\'')) {
|
||||
quote = c;
|
||||
}
|
||||
else {
|
||||
line[icout++] = c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
line[icout++] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!sep) {
|
||||
if (((c == '"') || (c == '\'')) && !backslash)
|
||||
quote = c;
|
||||
if (redirect != NULL) {
|
||||
if (redirect->name != NULL) {
|
||||
argc = -1;
|
||||
break;
|
||||
}
|
||||
redirect->name = line + icout;
|
||||
redirect = NULL;
|
||||
}
|
||||
else {
|
||||
argv[argc++] = line + icout;
|
||||
}
|
||||
if (quote == EOF)
|
||||
line[icout++] = c;
|
||||
inword = 1;
|
||||
}
|
||||
}
|
||||
backslash = 0;
|
||||
}
|
||||
if (redirect != NULL) {
|
||||
showError (filename, lineno, "Illegal redirection.");
|
||||
continue;
|
||||
}
|
||||
if (argc < 0)
|
||||
break;
|
||||
if (quote != EOF) {
|
||||
showError (filename, lineno, "Unbalanced quote.");
|
||||
continue;
|
||||
}
|
||||
if (backslash) {
|
||||
showError (filename, lineno, "Trailing backslash.");
|
||||
continue;
|
||||
}
|
||||
if (inword)
|
||||
line[icout++] = '\0';
|
||||
argv[argc] = NULL;
|
||||
|
||||
/*
|
||||
* Special case -- Redirected input but no command
|
||||
* Treat as if 'iocsh filename'.
|
||||
*/
|
||||
if ((argc == 0) && (redirects[0].name != NULL)) {
|
||||
const char *commandFile = redirects[0].name;
|
||||
redirects[0].name = NULL;
|
||||
if (openRedirect(filename, lineno, redirects) < 0)
|
||||
continue;
|
||||
startRedirect(filename, lineno, redirects);
|
||||
iocshBody(commandFile, NULL);
|
||||
stopRedirect(filename, lineno, redirects);
|
||||
continue;
|
||||
}
|
||||
if (openRedirect(filename, lineno, redirects) < 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Look up command
|
||||
*/
|
||||
if (argc) {
|
||||
/*
|
||||
* Special command?
|
||||
*/
|
||||
if (strncmp (argv[0], "exit", 4) == 0)
|
||||
break;
|
||||
if ((strcmp (argv[0], "?") == 0)
|
||||
|| (strncmp (argv[0], "help", 4) == 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;
|
||||
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((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) {
|
||||
const char *newPrompt;
|
||||
if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL)
|
||||
prompt = newPrompt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fp && (fp != stdin))
|
||||
fclose (fp);
|
||||
if (redirects != NULL) {
|
||||
stopRedirect(filename, lineno, redirects);
|
||||
free (redirects);
|
||||
}
|
||||
free(line);
|
||||
free (argv);
|
||||
free (argBuf);
|
||||
errlogFlush();
|
||||
if (readlineContext)
|
||||
epicsReadlineEnd(readlineContext);
|
||||
epicsThreadSetOkToBlock( wasOkToBlock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* External access to the command interpreter
|
||||
*/
|
||||
int epicsShareAPI
|
||||
iocsh (const char *pathname)
|
||||
{
|
||||
return iocshBody(pathname, NULL);
|
||||
}
|
||||
|
||||
int epicsShareAPI
|
||||
iocshCmd (const char *cmd)
|
||||
{
|
||||
if (cmd == NULL)
|
||||
return 0;
|
||||
return iocshBody(NULL, cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal commands
|
||||
*/
|
||||
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);
|
||||
return;
|
||||
case iocshArgInt: break;
|
||||
case iocshArgDouble: break;
|
||||
}
|
||||
if(setString == NULL) {
|
||||
switch(v->type) {
|
||||
default: break;
|
||||
case iocshArgInt:
|
||||
printf("%s = %d\n", v->name, *(int *)v->pval);
|
||||
break;
|
||||
case iocshArgDouble:
|
||||
printf("%s = %g\n", v->name, *(double *)v->pval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch(v->type) {
|
||||
default: break;
|
||||
case iocshArgInt:
|
||||
{
|
||||
char *endp;
|
||||
long ltmp = strtol(setString, &endp, 0);
|
||||
if((*setString != '\0') && (*endp == '\0'))
|
||||
*(int *)v->pval = ltmp;
|
||||
else
|
||||
printf("Invalid value -- value of %s not changed.\n", v->name);
|
||||
break;
|
||||
}
|
||||
case iocshArgDouble:
|
||||
{
|
||||
char *endp;
|
||||
double dtmp = epicsStrtod(setString, &endp);
|
||||
if((*setString != '\0') && (*endp == '\0'))
|
||||
*(double *)v->pval = dtmp;
|
||||
else
|
||||
printf("Invalid value -- value of %s not changed.\n", v->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void varCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
struct iocshVariable *v;
|
||||
if(args[0].sval == NULL) {
|
||||
for (v = iocshVariableHead ; v != NULL ; v = v->next)
|
||||
varHandler(v->pVarDef, args[1].sval);
|
||||
}
|
||||
else {
|
||||
v = (iocshVariable *)registryFind(iocshVarID, args[0].sval);
|
||||
if (v == NULL) {
|
||||
printf("%s -- no such variable.\n", args[0].sval);
|
||||
}
|
||||
else {
|
||||
varHandler(v->pVarDef, args[1].sval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* iocshCmd */
|
||||
static const iocshArg iocshCmdArg0 = { "command",iocshArgString};
|
||||
static const iocshArg *iocshCmdArgs[1] = {&iocshCmdArg0};
|
||||
static const iocshFuncDef iocshCmdFuncDef = {"iocshCmd",1,iocshCmdArgs};
|
||||
static void iocshCmdCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocshCmd(args[0].sval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dummy internal commands -- register and install in command table
|
||||
* so they show up in the help display
|
||||
*/
|
||||
|
||||
/* comment */
|
||||
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 *)
|
||||
{
|
||||
}
|
||||
|
||||
/* exit */
|
||||
static const iocshFuncDef exitFuncDef =
|
||||
{"exit",0,0};
|
||||
static void exitCallFunc(const iocshArgBuf *)
|
||||
{
|
||||
}
|
||||
|
||||
static void localRegister (void)
|
||||
{
|
||||
iocshRegister(&commentFuncDef,commentCallFunc);
|
||||
iocshRegister(&exitFuncDef,exitCallFunc);
|
||||
iocshRegister(&helpFuncDef,helpCallFunc);
|
||||
iocshRegister(&iocshCmdFuncDef,iocshCmdCallFunc);
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
/*
|
||||
* Register local commands on application startup
|
||||
*/
|
||||
class IocshRegister {
|
||||
public:
|
||||
IocshRegister() { localRegister(); }
|
||||
};
|
||||
static IocshRegister iocshRegisterObj;
|
||||
81
src/libCom/iocsh/iocsh.h
Normal file
81
src/libCom/iocsh/iocsh.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, 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.
|
||||
\*************************************************************************/
|
||||
/* iocsh.h ioc: call registered function*/
|
||||
/* Author: Marty Kraimer Date: 27APR2000 */
|
||||
|
||||
#ifndef INCiocshH
|
||||
#define INCiocshH
|
||||
|
||||
#include <stdio.h>
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
iocshArgInt,
|
||||
iocshArgDouble,
|
||||
iocshArgString,
|
||||
iocshArgPdbbase,
|
||||
iocshArgArgv,
|
||||
iocshArgPersistentString
|
||||
}iocshArgType;
|
||||
|
||||
typedef union iocshArgBuf {
|
||||
int ival;
|
||||
double dval;
|
||||
char *sval;
|
||||
void *vval;
|
||||
struct {
|
||||
int ac;
|
||||
char **av;
|
||||
} aval;
|
||||
}iocshArgBuf;
|
||||
|
||||
typedef struct iocshVarDef {
|
||||
const char *name;
|
||||
iocshArgType type;
|
||||
void * pval;
|
||||
}iocshVarDef;
|
||||
|
||||
typedef struct iocshArg {
|
||||
const char *name;
|
||||
iocshArgType type;
|
||||
}iocshArg;
|
||||
|
||||
typedef struct iocshFuncDef {
|
||||
const char *name;
|
||||
int nargs;
|
||||
const iocshArg * const *arg;
|
||||
}iocshFuncDef;
|
||||
|
||||
typedef void (*iocshCallFunc)(const iocshArgBuf *argBuf);
|
||||
|
||||
epicsShareFunc void epicsShareAPI iocshRegister(
|
||||
const iocshFuncDef *piocshFuncDef, iocshCallFunc func);
|
||||
epicsShareFunc void epicsShareAPI iocshRegisterVariable (
|
||||
const iocshVarDef *piocshVarDef);
|
||||
|
||||
/* iocshFree frees storage used by iocshRegister*/
|
||||
/* This should only be called when iocsh is no longer needed*/
|
||||
epicsShareFunc void epicsShareAPI iocshFree(void);
|
||||
|
||||
epicsShareFunc int epicsShareAPI iocsh(const char *pathname);
|
||||
epicsShareFunc int epicsShareAPI iocshCmd(const char *cmd);
|
||||
|
||||
/* 'weak' link to pdbbase */
|
||||
epicsShareExtern struct dbBase **iocshPpdbbase;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*INCiocshH*/
|
||||
290
src/libCom/iocsh/libComRegister.c
Normal file
290
src/libCom/iocsh/libComRegister.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The University of Saskatchewan
|
||||
* 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 file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "iocsh.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "envDefs.h"
|
||||
#include "osiUnistd.h"
|
||||
#include "logClient.h"
|
||||
#include "errlog.h"
|
||||
#include "libComRegister.h"
|
||||
|
||||
|
||||
/* chdir */
|
||||
static const iocshArg chdirArg0 = { "directory name",iocshArgString};
|
||||
static const iocshArg * const chdirArgs[1] = {&chdirArg0};
|
||||
static const iocshFuncDef chdirFuncDef = {"cd",1,chdirArgs};
|
||||
static void chdirCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
int status;
|
||||
status = chdir(args[0].sval);
|
||||
if (status) {
|
||||
printf ("Invalid directory path ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* print current working directory */
|
||||
static const iocshFuncDef pwdFuncDef = { "pwd", 0, 0 };
|
||||
static void pwdCallFunc (const iocshArgBuf *args)
|
||||
{
|
||||
char buf[256];
|
||||
char *pwd = getcwd ( buf, sizeof(buf) - 1 );
|
||||
if ( pwd ) {
|
||||
printf ( "%s\n", pwd );
|
||||
}
|
||||
}
|
||||
|
||||
/* epicsEnvSet */
|
||||
static const iocshArg epicsEnvSetArg0 = { "name",iocshArgString};
|
||||
static const iocshArg epicsEnvSetArg1 = { "value",iocshArgString};
|
||||
static const iocshArg * const epicsEnvSetArgs[2] = {&epicsEnvSetArg0,&epicsEnvSetArg1};
|
||||
static const iocshFuncDef epicsEnvSetFuncDef = {"epicsEnvSet",2,epicsEnvSetArgs};
|
||||
static void epicsEnvSetCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *name = args[0].sval;
|
||||
char *value = args[1].sval;
|
||||
|
||||
if (name == NULL) {
|
||||
printf ("Missing environment variable name argument.\n");
|
||||
return;
|
||||
}
|
||||
if (value == NULL) {
|
||||
printf ("Missing environment variable value argument.\n");
|
||||
return;
|
||||
}
|
||||
epicsEnvSet (name, value);
|
||||
}
|
||||
|
||||
/* epicsParamShow */
|
||||
static const iocshFuncDef epicsParamShowFuncDef = {"epicsParamShow",0,NULL};
|
||||
static void epicsParamShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsPrtEnvParams ();
|
||||
}
|
||||
|
||||
/* epicsPrtEnvParams */
|
||||
static const iocshFuncDef epicsPrtEnvParamsFuncDef = {"epicsPrtEnvParams",0,0};
|
||||
static void epicsPrtEnvParamsCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsPrtEnvParams ();
|
||||
}
|
||||
|
||||
/* epicsEnvShow */
|
||||
static const iocshArg epicsEnvShowArg0 = { "[name]",iocshArgString};
|
||||
static const iocshArg * const epicsEnvShowArgs[1] = {&epicsEnvShowArg0};
|
||||
static const iocshFuncDef epicsEnvShowFuncDef = {"epicsEnvShow",1,epicsEnvShowArgs};
|
||||
static void epicsEnvShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsEnvShow (args[0].sval);
|
||||
}
|
||||
|
||||
/* iocLogInit */
|
||||
static const iocshFuncDef iocLogInitFuncDef = {"iocLogInit",0};
|
||||
static void iocLogInitCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocLogInit ();
|
||||
}
|
||||
|
||||
/* iocLogDisable */
|
||||
static const iocshArg iocLogDisableArg0 = {"(0,1)=>(false,true)",iocshArgInt};
|
||||
static const iocshArg * const iocLogDisableArgs[1] = {&iocLogDisableArg0};
|
||||
static const iocshFuncDef iocLogDisableFuncDef = {"setIocLogDisable",1,iocLogDisableArgs};
|
||||
static void iocLogDisableCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocLogDisable = args[0].ival;
|
||||
}
|
||||
|
||||
/* iocLogShow */
|
||||
static const iocshArg iocLogShowArg0 = {"level",iocshArgInt};
|
||||
static const iocshArg * const iocLogShowArgs[1] = {&iocLogShowArg0};
|
||||
static const iocshFuncDef iocLogShowFuncDef = {"iocLogShow",1,iocLogShowArgs};
|
||||
static void iocLogShowCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
iocLogShow (args[0].ival);
|
||||
}
|
||||
|
||||
/* eltc */
|
||||
static const iocshArg eltcArg0 = {"(0,1)=>(false,true)",iocshArgInt};
|
||||
static const iocshArg * const eltcArgs[1] = {&eltcArg0};
|
||||
static const iocshFuncDef eltcFuncDef = {"eltc",1,eltcArgs};
|
||||
static void eltcCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
eltc(args[0].ival);
|
||||
}
|
||||
|
||||
/* errlogInit */
|
||||
static const iocshArg errlogInitArg0 = { "bufsize",iocshArgInt};
|
||||
static const iocshArg * const errlogInitArgs[1] = {&errlogInitArg0};
|
||||
static const iocshFuncDef errlogInitFuncDef =
|
||||
{"errlogInit",1,errlogInitArgs};
|
||||
static void errlogInitCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
errlogInit(args[0].ival);
|
||||
}
|
||||
|
||||
/* errlogInit2 */
|
||||
static const iocshArg errlogInit2Arg0 = { "bufSize",iocshArgInt};
|
||||
static const iocshArg errlogInit2Arg1 = { "maxMsgSize",iocshArgInt};
|
||||
static const iocshArg * const errlogInit2Args[] =
|
||||
{&errlogInit2Arg0, &errlogInit2Arg1};
|
||||
static const iocshFuncDef errlogInit2FuncDef =
|
||||
{"errlogInit2", 2, errlogInit2Args};
|
||||
static void errlogInit2CallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
errlogInit2(args[0].ival, args[1].ival);
|
||||
}
|
||||
|
||||
/* epicsThreadShowAll */
|
||||
static const iocshArg epicsThreadShowAllArg0 = { "level",iocshArgInt};
|
||||
static const iocshArg * const epicsThreadShowAllArgs[1] = {&epicsThreadShowAllArg0};
|
||||
static const iocshFuncDef epicsThreadShowAllFuncDef =
|
||||
{"epicsThreadShowAll",1,epicsThreadShowAllArgs};
|
||||
static void epicsThreadShowAllCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsThreadShowAll(args[0].ival);
|
||||
}
|
||||
|
||||
/* thread (thread information) */
|
||||
static const iocshArg threadArg0 = { "[-level] [thread ...]", iocshArgArgv};
|
||||
static const iocshArg * const threadArgs[1] = { &threadArg0 };
|
||||
static const iocshFuncDef threadFuncDef = {"thread",1,threadArgs};
|
||||
static void threadCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
int i = 1;
|
||||
int first = 1;
|
||||
int level = 0;
|
||||
const char *cp;
|
||||
epicsThreadId tid;
|
||||
unsigned long ltmp;
|
||||
int argc = args[0].aval.ac;
|
||||
char **argv = args[0].aval.av;
|
||||
char *endp;
|
||||
|
||||
if ((i < argc) && (*(cp = argv[i]) == '-')) {
|
||||
level = atoi (cp + 1);
|
||||
i++;
|
||||
}
|
||||
if (i >= argc) {
|
||||
epicsThreadShowAll (level);
|
||||
return;
|
||||
}
|
||||
for ( ; i < argc ; i++) {
|
||||
cp = argv[i];
|
||||
ltmp = strtoul (cp, &endp, 0);
|
||||
if (*endp) {
|
||||
tid = epicsThreadGetId (cp);
|
||||
if (!tid) {
|
||||
printf ("*** argument %d (%s) is not a valid thread name ***\n", i, cp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tid = (epicsThreadId)ltmp;
|
||||
}
|
||||
if (first) {
|
||||
epicsThreadShow (0, level);
|
||||
first = 0;
|
||||
}
|
||||
epicsThreadShow (tid, level);
|
||||
}
|
||||
}
|
||||
|
||||
/* epicsMutexShowAll */
|
||||
static const iocshArg epicsMutexShowAllArg0 = { "onlyLocked",iocshArgInt};
|
||||
static const iocshArg epicsMutexShowAllArg1 = { "level",iocshArgInt};
|
||||
static const iocshArg * const epicsMutexShowAllArgs[2] =
|
||||
{&epicsMutexShowAllArg0,&epicsMutexShowAllArg1};
|
||||
static const iocshFuncDef epicsMutexShowAllFuncDef =
|
||||
{"epicsMutexShowAll",1,epicsMutexShowAllArgs};
|
||||
static void epicsMutexShowAllCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsMutexShowAll(args[0].ival,args[1].ival);
|
||||
}
|
||||
|
||||
/* epicsThreadSleep */
|
||||
static const iocshArg epicsThreadSleepArg0 = { "seconds",iocshArgDouble};
|
||||
static const iocshArg * const epicsThreadSleepArgs[1] = {&epicsThreadSleepArg0};
|
||||
static const iocshFuncDef epicsThreadSleepFuncDef =
|
||||
{"epicsThreadSleep",1,epicsThreadSleepArgs};
|
||||
static void epicsThreadSleepCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsThreadSleep(args[0].dval);
|
||||
}
|
||||
|
||||
/* epicsThreadResume */
|
||||
static const iocshArg epicsThreadResumeArg0 = { "[thread ...]", iocshArgArgv};
|
||||
static const iocshArg * const epicsThreadResumeArgs[1] = { &epicsThreadResumeArg0 };
|
||||
static const iocshFuncDef epicsThreadResumeFuncDef = {"epicsThreadResume",1,epicsThreadResumeArgs};
|
||||
static void epicsThreadResumeCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
int i;
|
||||
const char *cp;
|
||||
epicsThreadId tid;
|
||||
unsigned long ltmp;
|
||||
char nameBuf[64];
|
||||
int argc = args[0].aval.ac;
|
||||
char **argv = args[0].aval.av;
|
||||
char *endp;
|
||||
|
||||
for (i = 1 ; i < argc ; i++) {
|
||||
cp = argv[i];
|
||||
ltmp = strtoul(cp, &endp, 0);
|
||||
if (*endp) {
|
||||
tid = epicsThreadGetId(cp);
|
||||
if (!tid) {
|
||||
printf("*** argument %d (%s) is not a valid thread name ***\n", i, cp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!epicsThreadIsSuspended(tid)) {
|
||||
printf("*** Thread %s is not suspended ***\n", cp);
|
||||
continue;
|
||||
}
|
||||
epicsThreadResume(tid);
|
||||
}
|
||||
}
|
||||
|
||||
void epicsShareAPI libComRegister(void)
|
||||
{
|
||||
iocshRegister(&chdirFuncDef, chdirCallFunc);
|
||||
iocshRegister(&pwdFuncDef, pwdCallFunc);
|
||||
|
||||
iocshRegister(&epicsEnvSetFuncDef, epicsEnvSetCallFunc);
|
||||
iocshRegister(&epicsParamShowFuncDef, epicsParamShowCallFunc);
|
||||
iocshRegister(&epicsPrtEnvParamsFuncDef, epicsPrtEnvParamsCallFunc);
|
||||
iocshRegister(&epicsEnvShowFuncDef, epicsEnvShowCallFunc);
|
||||
|
||||
iocshRegister(&iocLogInitFuncDef, iocLogInitCallFunc);
|
||||
iocshRegister(&iocLogDisableFuncDef, iocLogDisableCallFunc);
|
||||
iocshRegister(&iocLogShowFuncDef, iocLogShowCallFunc);
|
||||
iocshRegister(&eltcFuncDef, eltcCallFunc);
|
||||
iocshRegister(&errlogInitFuncDef,errlogInitCallFunc);
|
||||
iocshRegister(&errlogInit2FuncDef,errlogInit2CallFunc);
|
||||
|
||||
iocshRegister(&epicsThreadShowAllFuncDef,epicsThreadShowAllCallFunc);
|
||||
iocshRegister(&threadFuncDef, threadCallFunc);
|
||||
iocshRegister(&epicsMutexShowAllFuncDef,epicsMutexShowAllCallFunc);
|
||||
iocshRegister(&epicsThreadSleepFuncDef,epicsThreadSleepCallFunc);
|
||||
iocshRegister(&epicsThreadResumeFuncDef,epicsThreadResumeCallFunc);
|
||||
}
|
||||
23
src/libCom/iocsh/libComRegister.h
Normal file
23
src/libCom/iocsh/libComRegister.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2007 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.
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef INC_libComRegister_H
|
||||
#define INC_libComRegister_H
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc void epicsShareAPI libComRegister(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INC_libComRegister_H */
|
||||
145
src/libCom/iocsh/osiRegister.c
Normal file
145
src/libCom/iocsh/osiRegister.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2007 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 file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "iocsh.h"
|
||||
#include "epicsThread.h"
|
||||
#include "epicsMutex.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "osiRegister.h"
|
||||
|
||||
/* epicsThreadShowAll */
|
||||
static const iocshArg epicsThreadShowAllArg0 = { "level",iocshArgInt};
|
||||
static const iocshArg * const epicsThreadShowAllArgs[1] = {&epicsThreadShowAllArg0};
|
||||
static const iocshFuncDef epicsThreadShowAllFuncDef =
|
||||
{"epicsThreadShowAll",1,epicsThreadShowAllArgs};
|
||||
static void epicsThreadShowAllCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsThreadShowAll(args[0].ival);
|
||||
}
|
||||
|
||||
/* thread (thread information) */
|
||||
static const iocshArg threadArg0 = { "[-level] [thread ...]", iocshArgArgv};
|
||||
static const iocshArg * const threadArgs[1] = { &threadArg0 };
|
||||
static const iocshFuncDef threadFuncDef = {"thread",1,threadArgs};
|
||||
static void threadCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
int i = 1;
|
||||
int first = 1;
|
||||
int level = 0;
|
||||
const char *cp;
|
||||
epicsThreadId tid;
|
||||
unsigned long ltmp;
|
||||
int argc = args[0].aval.ac;
|
||||
char **argv = args[0].aval.av;
|
||||
char *endp;
|
||||
|
||||
if ((i < argc) && (*(cp = argv[i]) == '-')) {
|
||||
level = atoi (cp + 1);
|
||||
i++;
|
||||
}
|
||||
if (i >= argc) {
|
||||
epicsThreadShowAll (level);
|
||||
return;
|
||||
}
|
||||
for ( ; i < argc ; i++) {
|
||||
cp = argv[i];
|
||||
ltmp = strtoul (cp, &endp, 0);
|
||||
if (*endp) {
|
||||
tid = epicsThreadGetId (cp);
|
||||
if (!tid) {
|
||||
printf ("*** argument %d (%s) is not a valid thread name ***\n", i, cp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tid = (epicsThreadId)ltmp;
|
||||
}
|
||||
if (first) {
|
||||
epicsThreadShow (0, level);
|
||||
first = 0;
|
||||
}
|
||||
epicsThreadShow (tid, level);
|
||||
}
|
||||
}
|
||||
|
||||
/* epicsMutexShowAll */
|
||||
static const iocshArg epicsMutexShowAllArg0 = { "onlyLocked",iocshArgInt};
|
||||
static const iocshArg epicsMutexShowAllArg1 = { "level",iocshArgInt};
|
||||
static const iocshArg * const epicsMutexShowAllArgs[2] =
|
||||
{&epicsMutexShowAllArg0,&epicsMutexShowAllArg1};
|
||||
static const iocshFuncDef epicsMutexShowAllFuncDef =
|
||||
{"epicsMutexShowAll",1,epicsMutexShowAllArgs};
|
||||
static void epicsMutexShowAllCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsMutexShowAll(args[0].ival,args[1].ival);
|
||||
}
|
||||
|
||||
/* epicsThreadSleep */
|
||||
static const iocshArg epicsThreadSleepArg0 = { "seconds",iocshArgDouble};
|
||||
static const iocshArg * const epicsThreadSleepArgs[1] = {&epicsThreadSleepArg0};
|
||||
static const iocshFuncDef epicsThreadSleepFuncDef =
|
||||
{"epicsThreadSleep",1,epicsThreadSleepArgs};
|
||||
static void epicsThreadSleepCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
epicsThreadSleep(args[0].dval);
|
||||
}
|
||||
|
||||
/* epicsThreadResume */
|
||||
static const iocshArg epicsThreadResumeArg0 = { "[thread ...]", iocshArgArgv};
|
||||
static const iocshArg * const epicsThreadResumeArgs[1] = { &epicsThreadResumeArg0 };
|
||||
static const iocshFuncDef epicsThreadResumeFuncDef = {"epicsThreadResume",1,epicsThreadResumeArgs};
|
||||
static void epicsThreadResumeCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
int i;
|
||||
const char *cp;
|
||||
epicsThreadId tid;
|
||||
unsigned long ltmp;
|
||||
char nameBuf[64];
|
||||
int argc = args[0].aval.ac;
|
||||
char **argv = args[0].aval.av;
|
||||
char *endp;
|
||||
|
||||
for (i = 1 ; i < argc ; i++) {
|
||||
cp = argv[i];
|
||||
ltmp = strtoul(cp, &endp, 0);
|
||||
if (*endp) {
|
||||
tid = epicsThreadGetId(cp);
|
||||
if (!tid) {
|
||||
printf("*** argument %d (%s) is not a valid thread name ***\n", i, cp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (!epicsThreadIsSuspended(tid)) {
|
||||
printf("*** Thread %s is not suspended ***\n", cp);
|
||||
continue;
|
||||
}
|
||||
epicsThreadResume(tid);
|
||||
}
|
||||
}
|
||||
|
||||
void epicsShareAPI osiRegister(void)
|
||||
{
|
||||
iocshRegister(&epicsThreadShowAllFuncDef,epicsThreadShowAllCallFunc);
|
||||
iocshRegister(&threadFuncDef, threadCallFunc);
|
||||
iocshRegister(&epicsMutexShowAllFuncDef,epicsMutexShowAllCallFunc);
|
||||
iocshRegister(&epicsThreadSleepFuncDef,epicsThreadSleepCallFunc);
|
||||
iocshRegister(&epicsThreadResumeFuncDef,epicsThreadResumeCallFunc);
|
||||
}
|
||||
28
src/libCom/iocsh/osiRegister.h
Normal file
28
src/libCom/iocsh/osiRegister.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, 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.
|
||||
\*************************************************************************/
|
||||
/* osiRegister.h */
|
||||
/* Author: Marty Kraimer Date: 27APR2000 */
|
||||
|
||||
#ifndef INCosiRegisterH
|
||||
#define INCosiRegisterH
|
||||
|
||||
#include "shareLib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
epicsShareFunc void epicsShareAPI osiRegister(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*INCosiRegisterH*/
|
||||
91
src/libCom/iocsh/registry.c
Normal file
91
src/libCom/iocsh/registry.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, 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.
|
||||
\*************************************************************************/
|
||||
/*registry.c */
|
||||
|
||||
/* Author: Marty Kraimer Date: 08JUN99 */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "cantProceed.h"
|
||||
#include "epicsFindSymbol.h"
|
||||
#include "gpHash.h"
|
||||
#define epicsExportSharedSymbols
|
||||
#include "registry.h"
|
||||
|
||||
static void *gphPvt = 0;
|
||||
|
||||
static void registryInit(int tableSize)
|
||||
{
|
||||
if(tableSize==0) tableSize = DEFAULT_TABLE_SIZE;
|
||||
gphInitPvt(&gphPvt,tableSize);
|
||||
if(!gphPvt) cantProceed("registry why did gphInitPvt fail\n");
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI registrySetTableSize(int size)
|
||||
{
|
||||
if(gphPvt) {
|
||||
printf("registryInit already called\n");
|
||||
return(-1);
|
||||
}
|
||||
registryInit(size);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
epicsShareFunc int epicsShareAPI registryAdd(
|
||||
void *registryID,const char *name,void *data)
|
||||
{
|
||||
GPHENTRY *pentry;
|
||||
if(!gphPvt) registryInit(0);
|
||||
pentry = gphAdd(gphPvt,name,registryID);
|
||||
if(!pentry) return(FALSE);
|
||||
pentry->userPvt = data;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI registryChange(
|
||||
void *registryID,const char *name,void *data)
|
||||
{
|
||||
GPHENTRY *pentry;
|
||||
if(!gphPvt) registryInit(0);
|
||||
pentry = gphFind(gphPvt,(char *)name,registryID);
|
||||
if(!pentry) return(FALSE);
|
||||
pentry->userPvt = data;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
epicsShareFunc void * epicsShareAPI registryFind(
|
||||
void *registryID,const char *name)
|
||||
{
|
||||
GPHENTRY *pentry;
|
||||
if(name==0) return(0);
|
||||
if(registryID==0) return(epicsFindSymbol(name));
|
||||
if(!gphPvt) registryInit(0);
|
||||
pentry = gphFind(gphPvt,(char *)name,registryID);
|
||||
if(!pentry) return(0);
|
||||
return(pentry->userPvt);
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI registryFree()
|
||||
{
|
||||
if(!gphPvt) return;
|
||||
gphFreeMem(gphPvt);
|
||||
}
|
||||
|
||||
epicsShareFunc int epicsShareAPI registryDump(void)
|
||||
{
|
||||
if(!gphPvt) return(0);
|
||||
gphDump(gphPvt);
|
||||
return(0);
|
||||
}
|
||||
35
src/libCom/iocsh/registry.h
Normal file
35
src/libCom/iocsh/registry.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, 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.
|
||||
\*************************************************************************/
|
||||
#ifndef INCregistryh
|
||||
#define INCregistryh
|
||||
|
||||
#include "shareLib.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEFAULT_TABLE_SIZE 1024
|
||||
|
||||
epicsShareFunc int epicsShareAPI registryAdd(
|
||||
void *registryID,const char *name,void *data);
|
||||
epicsShareFunc void *epicsShareAPI registryFind(
|
||||
void *registryID,const char *name);
|
||||
epicsShareFunc int epicsShareAPI registryChange(
|
||||
void *registryID,const char *name,void *data);
|
||||
|
||||
epicsShareFunc int epicsShareAPI registrySetTableSize(int size);
|
||||
epicsShareFunc void epicsShareAPI registryFree();
|
||||
epicsShareFunc int epicsShareAPI registryDump(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INCregistryh */
|
||||
Reference in New Issue
Block a user