diff --git a/config/CONFIG_SITE b/config/CONFIG_SITE index e5218afd2..9d5c5bbfd 100644 --- a/config/CONFIG_SITE +++ b/config/CONFIG_SITE @@ -49,7 +49,7 @@ endif # ppc604 # vxipc # -CROSS_COMPILER_TARGET_ARCHS=vxWorks-68040 vxWorks-ppc604 +CROSS_COMPILER_TARGET_ARCHS= # If only a subset of the host architectures perform diff --git a/configure/CONFIG_COMMON b/configure/CONFIG_COMMON index e6da740f2..de65ceb2f 100644 --- a/configure/CONFIG_COMMON +++ b/configure/CONFIG_COMMON @@ -370,5 +370,12 @@ COMMON_INC += $(filter $(COMMON_DIR)/%, $(foreach file, $(INC), \ SOURCE_INC = $(wildcard $(file) $(SOURCE_INC_bbb) ) SOURCE_INC_bbb = $(foreach dir, $(ALL_SRC_DIRS), $(SOURCE_INC_aaa) ) SOURCE_INC_aaa = $(addsuffix /$(file), $(dir) ) + +# Command-line input support +OP_SYS_CFLAGS += -DEPICS_COMMANDLINE_LIBRARY=EPICS_COMMANDLINE_LIBRARY_$(COMMANDLINE_LIBRARY) + +LDLIBS_READLINE = -lreadline -lncurses +LDLIBS_LIBTECLA = -ltecla_r -lncurses +OP_SYS_LDLIBS += $(LDLIBS_$(COMMANDLINE_LIBRARY)) endif diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index 6fb206bf8..2662ec49b 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -124,3 +124,13 @@ CROSS_WARN=YES # Installation directory INSTALL_LOCATION=$(TOP) + +# Command-line input support +# +# Currently Supporting: +# EPICS - Built-in EPICS routines (no command-line editing/history) +# READLINE - GNU readline library +# LIBTECLA - LIBTECLA library +# +#COMMANDLINE_LIBRARY= +COMMANDLINE_LIBRARY=READLINE diff --git a/configure/os/CONFIG.Common.RTEMS b/configure/os/CONFIG.Common.RTEMS index 66a218fe8..bdb118b1f 100644 --- a/configure/os/CONFIG.Common.RTEMS +++ b/configure/os/CONFIG.Common.RTEMS @@ -35,7 +35,8 @@ CPP = $(RTEMS_BASE)/bin/$(CC_FOR_TARGET) -x c -E AR = $(RTEMS_BASE)/bin/$(AR_FOR_TARGET) LD = $(RTEMS_BASE)/bin/$(LD_FOR_TARGET) -r RTEMS_LDFLAGS := $(STATIC_LDFLAGS) $(LDFLAGS) -LINK.cpp = $(CCC) -o $@ $(RTEMS_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(LDLIBS) +LINK.cpp = $(CCC) -o $@ $(RTEMS_LDFLAGS) $(LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(LDLIBS) + RANLIB := $(RTEMS_BASE)/bin/$(RANLIB) #------------------------------------------------------- @@ -75,8 +76,8 @@ OS_CLASS = RTEMS #-------------------------------------------------- # Operating system flags -OP_SYS_LDLIBS = -lrtemsCom -lrtemscpu -lreadline -lcurses -lm -OP_SYS_LDFLAGS = $(CPU_CFLAGS) -u Init \ +OP_SYS_LDLIBS += -lrtemsCom -lrtemscpu -lm +OP_SYS_LDFLAGS += $(CPU_CFLAGS) -u Init \ $(PROJECT_RELEASE)/lib/no-dpmem.rel \ $(PROJECT_RELEASE)/lib/no-mp.rel \ $(PROJECT_RELEASE)/lib/no-part.rel \ diff --git a/configure/os/CONFIG.Common.darwin-ppc b/configure/os/CONFIG.Common.darwin-ppc index 9f54d2244..bad2f70af 100644 --- a/configure/os/CONFIG.Common.darwin-ppc +++ b/configure/os/CONFIG.Common.darwin-ppc @@ -25,14 +25,11 @@ OP_SYS_CFLAGS += -fno-common CPPSNCFLAGS += -no-cpp-precomp # -# Need to get some fink-installed packages (readline, etc.). -# If you don't have readline on your system you must remove -# or comment out these lines and make the appropriate changes -# to src/libCom/osi/os/Darwin/osdReadline.h +# Need to get some fink-installed packages # OP_SYS_CPPFLAGS += -I$(FINK_DIR)/include OP_SYS_LDFLAGS += -L$(FINK_DIR)/lib -OP_SYS_LDLIBS += -lreadline +OP_SYS_LDLIBS += # # Stuff that will be needed when going to shared libraries diff --git a/configure/os/CONFIG.Common.linux-mpc82xx b/configure/os/CONFIG.Common.linux-mpc82xx index 512231c5b..0faa7718f 100644 --- a/configure/os/CONFIG.Common.linux-mpc82xx +++ b/configure/os/CONFIG.Common.linux-mpc82xx @@ -21,8 +21,8 @@ POSIX_LDLIBS_NO = # -D_BSD_SOURCE for gethostname() in unistd.h as needed by cacChannelIO.cpp. OP_SYS_CPPFLAGS += -D_BSD_SOURCE OP_SYS_CPPFLAGS += -Dlinux -OP_SYS_LDFLAGS = -OP_SYS_LDLIBS = -lreadline -lcurses -lrt +OP_SYS_LDFLAGS += +OP_SYS_LDLIBS = -lrt #ARCH_DEP_CPPFLAGS += -D_X86_ diff --git a/configure/os/CONFIG.Common.linux-x86 b/configure/os/CONFIG.Common.linux-x86 index 9c25cc5b3..693760af2 100644 --- a/configure/os/CONFIG.Common.linux-x86 +++ b/configure/os/CONFIG.Common.linux-x86 @@ -23,8 +23,8 @@ POSIX_LDLIBS_NO = # -D_BSD_SOURCE for gethostname() in unistd.h as needed by cacChannelIO.cpp. OP_SYS_CPPFLAGS += -D_BSD_SOURCE OP_SYS_CPPFLAGS += -Dlinux -OP_SYS_LDFLAGS = -OP_SYS_LDLIBS = -lreadline -lcurses -lrt +OP_SYS_LDFLAGS += +OP_SYS_LDLIBS += -lrt ARCH_DEP_CPPFLAGS += -D_X86_ ARCH_DEP_CFLAGS += -mcpu=pentium @@ -36,4 +36,4 @@ ifdef CROSS endif #Allow R3.13 built extensions to load R3.14 shared libs -SYS_SHRLIB_LIBS += pthread readline curses rt +SYS_SHRLIB_LIBS += pthread rt diff --git a/configure/os/CONFIG.Common.vxWorksCommon b/configure/os/CONFIG.Common.vxWorksCommon index 300e0f5f8..62f355521 100644 --- a/configure/os/CONFIG.Common.vxWorksCommon +++ b/configure/os/CONFIG.Common.vxWorksCommon @@ -86,11 +86,11 @@ export TOOL_FAMILY = GNU #-------------------------------------------------- # Operating system flags -OP_SYS_CPPFLAGS = -DvxWorks -OP_SYS_CFLAGS = -fno-builtin -#OP_SYS_CFLAGS = -fno-builtin -fdollars-in-identifiers -OP_SYS_LDFLAGS = -OP_SYS_LDLIBS = +OP_SYS_CPPFLAGS += -DvxWorks +OP_SYS_CFLAGS += -fno-builtin +#OP_SYS_CFLAGS += -fno-builtin -fdollars-in-identifiers +OP_SYS_LDFLAGS += +OP_SYS_LDLIBS += # Fix for vxWorks headers using macros defined in # vxWorks.h but not including vxWorks.h diff --git a/configure/os/CONFIG.Common.win32-x86-cygwin b/configure/os/CONFIG.Common.win32-x86-cygwin index 192cb3c90..dc123db18 100644 --- a/configure/os/CONFIG.Common.win32-x86-cygwin +++ b/configure/os/CONFIG.Common.win32-x86-cygwin @@ -23,8 +23,8 @@ POSIX_LDLIBS_NO = # -D_BSD_SOURCE for gethostname() in unistd.h as needed by cacChannelIO.cpp. OP_SYS_CPPFLAGS += -DCYGWIN32 -U_WIN32 -OP_SYS_LDFLAGS = -####OP_SYS_LDLIBS = -lreadline -lcurses -lrt +OP_SYS_LDFLAGS += +####OP_SYS_LDLIBS += -lrt ARCH_DEP_CPPFLAGS += -D_X86_ diff --git a/src/iocsh/iocsh.cpp b/src/iocsh/iocsh.cpp index ec47af110..433952577 100644 --- a/src/iocsh/iocsh.cpp +++ b/src/iocsh/iocsh.cpp @@ -218,27 +218,14 @@ iocsh (const char *pathname) int argBufCapacity = 0; struct iocshCommand *found; struct iocshFuncDef const *piocshFuncDef; + void *readlineContext; /* * See if command interpreter is interactive */ if ((pathname == NULL) || (strcmp (pathname, "") == 0)) { - const char *historySize; if ((prompt = getenv ("IOCSH_PS1")) == NULL) prompt = "epics> "; - if (((historySize = getenv ("IOCSH_HISTSIZE")) == NULL) - && ((historySize = getenv ("HISTSIZE")) == NULL)) - historySize = "20"; - if (pathname == NULL) { - epicsStifleHistory (atoi (historySize)); - /* - * FIXME: Could enable tab-completion of commands here - */ - epicsBindKeys(); - } - else { - fp = stdin; - } } else { fp = fopen (pathname, "r"); @@ -253,24 +240,21 @@ iocsh (const char *pathname) 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; + } + /* * Read commands till EOF or exit */ - for (;;) { - /* - * Get a line - */ + while ((line = epicsReadline(prompt, readlineContext)) != NULL) { lineno++; - free (line); - line = epicsReadline (fp, prompt); - if (line == NULL) - break; - - /* - * If using readline, add non-blank lines to history - */ - if ((fp == NULL) && *line) - epicsAddHistory (line); /* * Ignore comment lines @@ -278,8 +262,11 @@ iocsh (const char *pathname) if (*line == '#') continue; - if ((prompt == NULL) && *line) - puts(line); + /* + * Echo commands read from scripts + */ + if ((prompt == NULL) && *line) + puts(line); /* * Break line into words @@ -471,10 +458,10 @@ iocsh (const char *pathname) } if (fp && (fp != stdin)) fclose (fp); - free (line); free (argv); free (argBuf); errlogFlush(); + epicsReadlineEnd(readlineContext); return 0; } diff --git a/src/libCom/osi/os/Darwin/osdReadline.h b/src/libCom/osi/os/Darwin/osdReadline.h deleted file mode 100644 index 133156ab0..000000000 --- a/src/libCom/osi/os/Darwin/osdReadline.h +++ /dev/null @@ -1,23 +0,0 @@ -/*************************************************************************\ -* Copyright (c) 2002 The University of Saskatchewan -* 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. -\*************************************************************************/ -/* - * $Id$ - * - * Author: Eric Norum - */ - -#ifndef _OSD_READLINE_H_ -#define _OSD_READLINE_H_ - -/* - * If you don't have the fink readline package installed, uncomment - * the `FAKE' line and comment out the `REAL' line. - */ -/* #define IOCSH_FAKE_READLINE */ -#define IOCSH_REAL_READLINE - -#endif /* _OSD_READLINE_H_ */ diff --git a/src/libCom/osi/os/Linux/osdReadline.h b/src/libCom/osi/os/Linux/osdReadline.h deleted file mode 100644 index 073ed7d1a..000000000 --- a/src/libCom/osi/os/Linux/osdReadline.h +++ /dev/null @@ -1,18 +0,0 @@ -/*************************************************************************\ -* 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 _OSD_READLINE_H_ -#define _OSD_READLINE_H_ - -/* - * Use readline library. - */ -#define IOCSH_REAL_READLINE - -#endif /* _OSD_READLINE_H_ */ diff --git a/src/libCom/osi/os/RTEMS/osdReadline.h b/src/libCom/osi/os/RTEMS/osdReadline.h deleted file mode 100644 index 073ed7d1a..000000000 --- a/src/libCom/osi/os/RTEMS/osdReadline.h +++ /dev/null @@ -1,18 +0,0 @@ -/*************************************************************************\ -* 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 _OSD_READLINE_H_ -#define _OSD_READLINE_H_ - -/* - * Use readline library. - */ -#define IOCSH_REAL_READLINE - -#endif /* _OSD_READLINE_H_ */ diff --git a/src/libCom/osi/os/default/epicsReadline.c b/src/libCom/osi/os/default/epicsReadline.c index cdb2e03d7..3c4f727f7 100644 --- a/src/libCom/osi/os/default/epicsReadline.c +++ b/src/libCom/osi/os/default/epicsReadline.c @@ -12,49 +12,231 @@ #define epicsExportSharedSymbols #include -#include -#if (defined (IOCSH_REAL_READLINE) && defined (IOCSH_FAKE_READLINE)) -# undef IOCSH_FAKE_READLINE +#define EPICS_COMMANDLINE_LIBRARY_EPICS 0 +#define EPICS_COMMANDLINE_LIBRARY_LIBTECLA 1 +#define EPICS_COMMANDLINE_LIBRARY_READLINE 2 + +#ifndef EPICS_COMMANDLINE_LIBRARY +#define EPICS_COMMANDLINE_LIBRARY EPICS_COMMANDLINE_LIBRARY_EPICS #endif -#if (defined (IOCSH_REAL_READLINE) || defined (IOCSH_FAKE_READLINE)) -#include -#include + +#if EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_LIBTECLA +#include +#include -#if (defined (IOCSH_REAL_READLINE)) -# include -# include -#endif +/* + * Create a command-line context + */ +void * epicsShareAPI +epicsReadlineBegin (FILE *in) +{ + GetLine *gl; + const char *histSize = getenv("IOCSH_HISTSIZE"); + int i; + + if (histSize == NULL) + i = 50; + else if ((i = atoi(histSize)) < 0) + i = 0; + gl = new_GetLine(200, i * 40); + if ((gl != NULL) && (in != NULL)) + gl_change_terminal(gl, in, stdout, NULL); + return gl; +} /* * Read a line of input */ char * epicsShareAPI -epicsReadline (FILE *fp, const char *prompt) +epicsReadline (const char *prompt, void *context) { + char *line; + char *nl; + + line = gl_get_line(context, prompt ? prompt : "", NULL, -1); + if ((line != NULL) && ((nl = strchr(line, '\n')) != NULL)) + *nl = '\0'; + return line; +} + +/* + * Destroy a command-line context + */ +void epicsShareAPI +epicsReadlineEnd(void *context) +{ + del_GetLine(context); +} + + +#elif EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_READLINE + +#include +#include +#include + +struct readlineContext { + FILE *in; + char *line; +}; + +/* + * Create a command-line context + */ +void * epicsShareAPI +epicsReadlineBegin(FILE *in) +{ + struct readlineContext *readlineContext; + + readlineContext = malloc(sizeof *readlineContext); + if (readlineContext != NULL) { + readlineContext->in = in; + readlineContext->line = NULL; + if (in == NULL) { + const char *histSize = getenv("IOCSH_HISTSIZE"); + int i; + + if (histSize == NULL) + i = 50; + else if ((i = atoi(histSize)) < 0) + i = 0; + stifle_history (i); + rl_bind_key ('\t', rl_insert); + } + } + return readlineContext; +} + +/* + * Read a line of input + */ +char * epicsShareAPI +epicsReadline (const char *prompt, void *context) +{ + struct readlineContext *readlineContext = context; + int c; /* char is unsigned on some archs, EOF is -ve */ char *line = NULL; int linelen = 0; int linesize = 50; - if (fp == NULL) -#ifdef IOCSH_REAL_READLINE - return readline (prompt); -#else - fp = stdin; -#endif + free (readlineContext->line); + readlineContext->line = NULL; + if (readlineContext->in == NULL) { + line = readline (prompt); + } + else { + line = (char *)malloc (linesize * sizeof *line); + if (line == NULL) { + printf ("Out of memory!\n"); + return NULL; + } + if (prompt) { + fputs (prompt, stdout); + fflush (stdout); + } + while ((c = getc (readlineContext->in)) != '\n') { + if (c == EOF) { + free (line); + line = NULL; + break; + } + if ((linelen + 1) >= linesize) { + char *cp; + + linesize += 50; + cp = (char *)realloc (line, linesize * sizeof *line); + if (cp == NULL) { + printf ("Out of memory!\n"); + free (line); + line = NULL; + break; + } + line = cp; + } + line[linelen++] = c; + } + if (line) + line[linelen] = '\0'; + } + readlineContext->line = line; + if (line && line[0] != '#') + add_history (line); + return line; +} + +/* + * Destroy a command-line context + */ +void epicsShareAPI +epicsReadlineEnd (void *context) +{ + struct readlineContext *readlineContext = context; + + if (readlineContext) { + free(readlineContext->line); + free(readlineContext); + } +} + + +#elif EPICS_COMMANDLINE_LIBRARY == EPICS_COMMANDLINE_LIBRARY_EPICS + +struct readlineContext { + FILE *in; + char *line; +}; + +/* + * Create a command-line context + */ +void * epicsShareAPI +epicsReadlineBegin(FILE *in) +{ + struct readlineContext *readlineContext; + + readlineContext = malloc(sizeof *readlineContext); + if (readlineContext != NULL) { + readlineContext->in = in; + readlineContext->line = NULL; + } + return readlineContext; +} + +/* + * Read a line of input + */ +char * epicsShareAPI +epicsReadline (const char *prompt, void *context) +{ + struct readlineContext *readlineContext = context; + + int c; /* char is unsigned on some archs, EOF is -ve */ + char *line = NULL; + int linelen = 0; + int linesize = 50; + FILE *in; + + free (readlineContext->line); + readlineContext->line = NULL; + if ((in = readlineContext->in) == NULL) { + in = stdin; + if (prompt != NULL) { + fputs (prompt, stdout); + fflush (stdout); + } + } line = (char *)malloc (linesize * sizeof *line); if (line == NULL) { printf ("Out of memory!\n"); return NULL; } if (prompt) { - fputs (prompt, stdout); - fflush (stdout); } - while ((c = getc (fp)) != '\n') { + while ((c = getc (in)) != '\n') { if (c == EOF) { free (line); return NULL; @@ -74,28 +256,26 @@ epicsReadline (FILE *fp, const char *prompt) line[linelen++] = c; } line[linelen] = '\0'; + readlineContext->line = line; return line; } -void epicsShareAPI epicsStifleHistory (int n) +/* + * Destroy a command-line context + */ +void epicsShareAPI +epicsReadlineEnd (void *context) { -#if (defined (IOCSH_REAL_READLINE)) - stifle_history (n); -#endif + struct readlineContext *readlineContext = context; + + if (readlineContext) { + free(readlineContext->line); + free(readlineContext); + } } -void epicsShareAPI epicsAddHistory (const char *line) -{ -#if (defined (IOCSH_REAL_READLINE)) - add_history (line); -#endif -} +#else -void epicsShareAPI epicsBindKeys (void) -{ -#if (defined (IOCSH_REAL_READLINE)) - rl_bind_key ('\t', rl_insert); -#endif -} +# error "Unsupported EPICS_COMMANDLINE_LIBRARY" -#endif /* defined (IOCSH_REAL_READLINE) || defined (IOCSH_FAKE_READLINE) */ +#endif diff --git a/src/libCom/osi/os/default/epicsReadline.h b/src/libCom/osi/os/default/epicsReadline.h index 6e0463b5c..f6ddf2791 100644 --- a/src/libCom/osi/os/default/epicsReadline.h +++ b/src/libCom/osi/os/default/epicsReadline.h @@ -17,10 +17,9 @@ extern "C" { #include #include -epicsShareFunc char * epicsShareAPI epicsReadline (FILE *fp, const char *prompt); -epicsShareFunc void epicsShareAPI epicsStifleHistory (int n); -epicsShareFunc void epicsShareAPI epicsAddHistory (const char *line); -epicsShareFunc void epicsShareAPI epicsBindKeys (void); +epicsShareFunc void * epicsShareAPI epicsReadlineBegin (FILE *in); +epicsShareFunc char * epicsShareAPI epicsReadline (const char *prompt, void *context); +epicsShareFunc void epicsShareAPI epicsReadlineEnd (void *context); #ifdef __cplusplus } diff --git a/src/libCom/osi/os/default/osdReadline.h b/src/libCom/osi/os/default/osdReadline.h deleted file mode 100644 index f696999f9..000000000 --- a/src/libCom/osi/os/default/osdReadline.h +++ /dev/null @@ -1,27 +0,0 @@ -/*************************************************************************\ -* 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 _OSD_READLINE_H_ -#define _OSD_READLINE_H_ - -/* - * Default version of osdReadline - * Don't use readline library, but do provide epicsReadline routines - * - * This wastes a few hundred bytes of memory if you're not using iocsh. - * If that many bytes is really important to you you can save it by - * going to the os-dependent directory and creating an osdReadline.h - * which defines neither of the following macros. - * - */ - -/* #define IOCSH_REAL_READLINE */ -#define IOCSH_FAKE_READLINE - -#endif /* _OSD_READLINE_H_ */