aboutsummaryrefslogtreecommitdiffhomepage
path: root/libslang/doc
diff options
context:
space:
mode:
Diffstat (limited to 'libslang/doc')
-rw-r--r--libslang/doc/OLD/help/README3
-rw-r--r--libslang/doc/OLD/help/makefile.djg18
-rw-r--r--libslang/doc/OLD/help/makefile.os270
-rw-r--r--libslang/doc/OLD/help/makefile.unx8
-rw-r--r--libslang/doc/OLD/help/slang.hlp241
-rw-r--r--libslang/doc/OLD/help/slhelp.c587
-rw-r--r--libslang/doc/README25
-rw-r--r--libslang/doc/grammar.txt131
-rw-r--r--libslang/doc/internal/rpn.txt60
-rw-r--r--libslang/doc/slangdoc.html27
-rw-r--r--libslang/doc/text/cref.txt4870
-rw-r--r--libslang/doc/text/cslang.txt2989
-rw-r--r--libslang/doc/text/slang.txt5642
-rw-r--r--libslang/doc/text/slangfun.txt5943
-rw-r--r--libslang/doc/tm/Makefile100
-rw-r--r--libslang/doc/tm/copyright.tm476
-rw-r--r--libslang/doc/tm/cref.tm3430
-rw-r--r--libslang/doc/tm/cslang.tm2033
-rw-r--r--libslang/doc/tm/fixtex.sl56
-rw-r--r--libslang/doc/tm/preface.tm95
-rw-r--r--libslang/doc/tm/regexp.tm98
-rw-r--r--libslang/doc/tm/rtl/array.tm378
-rw-r--r--libslang/doc/tm/rtl/assoc.tm76
-rw-r--r--libslang/doc/tm/rtl/bstr.tm151
-rw-r--r--libslang/doc/tm/rtl/debug.tm98
-rw-r--r--libslang/doc/tm/rtl/dir.tm223
-rw-r--r--libslang/doc/tm/rtl/eval.tm119
-rw-r--r--libslang/doc/tm/rtl/import.tm51
-rw-r--r--libslang/doc/tm/rtl/info.tm202
-rw-r--r--libslang/doc/tm/rtl/math.tm291
-rw-r--r--libslang/doc/tm/rtl/message.tm111
-rw-r--r--libslang/doc/tm/rtl/misc.tm201
-rw-r--r--libslang/doc/tm/rtl/ospath.tm77
-rw-r--r--libslang/doc/tm/rtl/posio.tm154
-rw-r--r--libslang/doc/tm/rtl/posix.tm285
-rw-r--r--libslang/doc/tm/rtl/stack.tm165
-rw-r--r--libslang/doc/tm/rtl/stdio.tm421
-rw-r--r--libslang/doc/tm/rtl/strops.tm736
-rw-r--r--libslang/doc/tm/rtl/struct.tm104
-rw-r--r--libslang/doc/tm/rtl/time.tm137
-rwxr-xr-xlibslang/doc/tm/rtl/tm-sort.sl153
-rw-r--r--libslang/doc/tm/rtl/type.tm245
-rwxr-xr-xlibslang/doc/tm/rtl/whatelse.sl116
-rw-r--r--libslang/doc/tm/slang.tm4077
-rw-r--r--libslang/doc/tm/slangfun.tm121
-rw-r--r--libslang/doc/tm/tools/Makefile46
-rw-r--r--libslang/doc/tm/tools/README67
-rw-r--r--libslang/doc/tm/tools/sl2tm.c216
-rw-r--r--libslang/doc/tm/tools/tm2txt.c726
49 files changed, 36649 insertions, 0 deletions
diff --git a/libslang/doc/OLD/help/README b/libslang/doc/OLD/help/README
new file mode 100644
index 0000000..fce6919
--- /dev/null
+++ b/libslang/doc/OLD/help/README
@@ -0,0 +1,3 @@
+The program this directory `slhelp' is capable of reading VMS style help
+files. The program `texconv' in ../doc is able to convert the TeX documents
+there to produce VMS style help files.
diff --git a/libslang/doc/OLD/help/makefile.djg b/libslang/doc/OLD/help/makefile.djg
new file mode 100644
index 0000000..67432c5
--- /dev/null
+++ b/libslang/doc/OLD/help/makefile.djg
@@ -0,0 +1,18 @@
+CC = gcc
+CFLAGS = -Wall -O6
+GO32 = C:\djgpp\bin\go32.exe
+SLIB = ../src#
+LFLAGS = -L$(SLIB) -lslang -lpc
+
+SUFFIXES = .c
+.SUFFIXES: $(SUFFIXES)
+
+.c.o:
+ $(CC) -c $(CFLAGS) -I$(SLIB) $*.c
+
+
+slhelp: slhelp.o
+ $(CC) slhelp.o $(LFLAGS) -o slhelp.386
+ coff2exe -s $(GO32) slhelp.386
+
+
diff --git a/libslang/doc/OLD/help/makefile.os2 b/libslang/doc/OLD/help/makefile.os2
new file mode 100644
index 0000000..9338fa9
--- /dev/null
+++ b/libslang/doc/OLD/help/makefile.os2
@@ -0,0 +1,70 @@
+#================ JED makefile for DMAKE 3.8 ======================
+# This makefile is for DMAKE, either under DOS or OS/2
+# The following OS/Compiler combinations are supported:
+#
+# Target Compiler Command Compiler
+# Operating Mnemoic Line
+# System
+#-----------------------------------------------------------------------
+# OS2 MSC OS=OS2 COMP=MSC Microsoft C
+# OS2 EMX OS=OS2 COMP=EMX emx/gcc
+#-----------------------------------------------------------------------
+MODEL = L
+#-----------------------------------------------------------------------
+# default setup for EMX under OS/2, optimized version
+# change values below or override with -e switch on command line
+#-----------------------------------------------------------------------
+OS=OS2
+COMP=EMX
+OPT=Y
+#-----------------------------------------------------------------------
+.IF $(TOS) == $(NULL)
+ TOS = $(OS)
+.END
+.IF $(OS) == OS2
+#========================================================================
+#========================= OS2 - MSC ====================================
+#========================================================================
+ .IF $(COMP) == MSC
+ CC = cl -nologo -MT
+ LIB_CMD = lib
+ .IF $(OPT) == N
+ CDBUG = -Od -Zi -W2
+ LDEBUG = -Zi
+ .ELSE
+ CDBUG =
+ LDEBUG =
+ .END
+ CDEBUG = $(CDBUG)
+ O = .obj
+ LFLAGS2 = setargv.obj $(SLANG).lib $(SLIB)os2sl16.def -link /NOE $(SLIB)
+#========================================================================
+#========================= OS2 - EMX ====================================
+#========================================================================
+ .ELIF $(COMP) == EMX
+ CC = gcc -Zmtd
+ .IF $(OPT) == N
+ CDEBUG =-g
+ LDEBUG =
+ .ELSE
+ CDEBUG = -O
+ LDEBUG =
+ .END
+ O = .o
+ LFLAGS2 = $(SLIB)os2sl.def -L$(SLIB) -l$(SLANG)
+ .ENDIF
+.ENDIF
+
+CFLAGS=$(CDEBUG) -I$(SLIB) -DHAS_MEMSET
+LFLAGS = $(LDEBUG)
+
+SLIB = ..\src\\
+SLANG = slang
+
+.c$O:
+ $(CC) -c $(CFLAGS) $*.c
+
+slhelp : slhelp.exe
+
+slhelp.exe: slhelp$O
+ $(CC) $(LFLAGS) -o $@ slhelp$O $(LFLAGS2)
diff --git a/libslang/doc/OLD/help/makefile.unx b/libslang/doc/OLD/help/makefile.unx
new file mode 100644
index 0000000..e87eaa0
--- /dev/null
+++ b/libslang/doc/OLD/help/makefile.unx
@@ -0,0 +1,8 @@
+# Uncomment if you have gcc
+# CC = gcc
+#
+# If you compiled with termcap, uncomment next line.
+# THETERMCAP = -ltermcap
+
+slhelp: slhelp.c
+ $(CC) $(CFLAGS) slhelp.c -I../src -L../src -o slhelp -lslang $(THETERMCAP)
diff --git a/libslang/doc/OLD/help/slang.hlp b/libslang/doc/OLD/help/slang.hlp
new file mode 100644
index 0000000..254031e
--- /dev/null
+++ b/libslang/doc/OLD/help/slang.hlp
@@ -0,0 +1,241 @@
+Help file for slang
+
+1 Interpreter
+ See readme files for information--- no help file yet.
+1 Keyboard-Interface
+ SLang's keyboard interface is designed to allow one to read a character
+ at a time in a system independent manner. To initialize the interface,
+ one must first call the function `SLang_init_tty'. Before exiting the
+ program, the function `SLang_reset_tty' must be called to restore the
+ keyboard interface to its original state. This is particularly true for
+ MSDOS since INT-9 is hooked by S-Lang.
+
+2 Functions
+
+3 init_tty
+
+ Prototype: int SLang_init_tty (int abort_char, int flow_ctrl, int opost);
+
+ This function must be called to initialize the tty for single character
+ input. The first parameter `abort_char' must lie in the range 0-255 and
+ is used as an abort character. By default, pressing this character sets
+ the global variable `SLang_Error' to USER_BREAK. See help on the function
+ `SLang_set_abort_signal' to change the default action.
+
+ If the second parameter `flow_ctrl' is non-zero, flow control is enabled.
+
+ If the third parmeter `opost' is zero, output processing is NOT turned on.
+ A value of zero is required for SLang's screen management routines (SLsmg)
+ to work properly.
+
+ This function returns 0 upon success. In addition, if the global variable
+ SLang_TT_Baud_Rate == 0 when this function is called, SLang will attempt
+ to determine the terminals baud rate and set this variable accordingly. As
+ far as the SLang library is concerned, if SLang_TT_Baud_Rate is less than
+ or equal to zero, the baud rate is effectively infinite.
+
+3 reset_tty
+
+ Prototype: void SLang_reset_tty (void);
+
+ This function must be called to reset the tty to the state the terminal
+ was in before a previous call to `SLang_init_tty'.
+
+3 getkey
+
+ Prototype: unsigned int SLang_getkey (void);
+
+ This function returns a single key from the tty. If the read fails,
+ 0xFFFF is returned. Before attempting to use this function, one myust
+ first call SLang_init_tty to initialize the terminal.
+
+ If the abort character is pressed while this function is called, it will
+ return the value of the abort character. In addition, the global variable
+ SLKeyBoard_Quit will be set and SLang_Error will will be set to USER_BREAK
+ unless the variable SLang_Ignore_User_Abort is non-zero.
+
+3 unget_keystring
+
+ Prototype: void SLang_ungetkey_string (unsigned char *buf, int buflen);
+
+3 buffer_keystring
+
+ Prototype: void SLang_buffer_keystring (unsigned char *buf, int buflen);
+
+3 ungetkey
+
+ Prototype: void SLang_ungetkey (unsigned char ch);
+
+3 flush_input
+
+ Prototype: void SLang_flush_input (void);
+
+3 input_pending
+
+ Prototype int SLang_input_pending (int tsecs);
+
+3 set_abort_signal
+
+ Prototype: void SLang_set_abort_signal (void (*f)(int));
+
+ If SIGINT is generated, the function p1 will be called. If `f' is NULL
+ the SLang default signal handler is called. This sets SLang_Error to
+ USER_BREAK. I suspect most users will simply want to pass NULL.
+
+2 Variables
+3 Abort_Char
+
+ int SLang_Abort_Char;
+ The value of the character (0-255) used to trigger SIGINT
+
+3 Ignore_User_Abort
+
+ int SLang_Ignore_User_Abort;
+ If non-zero, pressing the abort character will not result in USER_BREAK
+ SLang_Error.
+
+3 KeyBoard_Quit
+
+ volatile int SLKeyBoard_Quit
+
+3 TT_Baud_Rate
+
+ int SLang_TT_Baud_Rate;
+
+ If this value is zero before SLang_init_tty is called, after the call, it
+ will be set to the baud rate if the terminal on systems which support it.
+
+1Screen_Management
+ S-Lang's screen management routines are located in the slsmg.c file. All
+ exported functions and variables are prefixed by `SLsmg', e.g., `SLsmg_cls'.
+ The screen management code uses the `SLtt' routines for writing output to
+ the terminal.
+
+ To initialize the screen management system, call `SLtt_get_terminfo' first
+ to initialize the display system. Then call `SLsmg_init_smg' to initialize
+ the SLsmg routines. If you are going to read characters from the keyboard,
+ it is also a good idea to initialize the tty at this point via the
+ SLang_init_tty function (See `Keyboard').
+
+ Before exiting the program, call the approriate routines to reset the
+ terminal and display system. Basically, your program will look like
+ something like:
+\begin{verbatim}
+ #include "slang.h"
+
+ int main ()
+ {
+ SLtt_get_terminfo ();
+ SLang_init_tty (7, 0, 0);
+ SLsmg_init_smg ();
+
+ /* do stuff .... */
+
+ SLsmg_reset_smg ();
+ SLang_reset_tty ();
+ return 0;
+ }
+\end{verbatim}
+
+2Functions
+3erase_eol
+ Prototype: void SLsmg_erase_eol (void);
+ Erase line from current position to the end of the line.
+3gotorc
+ Prototype: void SLsmg_gotorc (int row, int col);
+ Move cursor position to ('row', 'col'). (0,0) corresponds to the top left
+ corner of the screen.
+3erase_eos
+ Prototype: void SLsmg_erase_eos (void);
+ Erase fro the current position to the end of the screen.
+3reverse_video
+ Prototype: void SLsmg_reverse_video (void);
+ Start writing characters in reverse video.
+3set_color
+ Prototype: void SLsmg_set_color (int obj);
+ Set the character attributes to those of 'obj'.
+3normal_video
+ Prototype: void SLsmg_normal_video (void);
+ Turn off characters attributes and set attributes to object 0.
+3printf
+ Prototype: void SLsmg_printf (char *, ...);
+ Write a formatted string to the virtual display.
+3vprintf
+ Prototype: void SLsmg_vprintf (char *, va_list);
+ Like 'SLsmg_printf' but uses a variable argument list.
+3write_string
+ Prototype: void SLsmg_write_string (char *);
+3write_char
+ Prototype: void SLsmg_write_char (char);
+3write_nchars
+ Prototype: void SLsmg_write_nchars (char *, int);
+3cls
+ Prototype: void SLsmg_cls (void);
+ Clear the screen
+3refresh
+ Prototype: void SLsmg_refresh (void);
+ Make the physical display look like the virtual display.
+3touch_lines
+ Prototype: void SLsmg_touch_lines (int row, int n);
+ Mark screen rows 'row', 'row + 1', ... 'row + (n - 1)' as modified.
+3init_smg
+ Prototype: int SLsmg_init_smg (void);
+ Must be called before any of the other routines will work.
+3reset_smg
+ Prototype: void SLsmg_reset_smg (void);
+3char_at
+ unsigned short SLsmg_char_at(void);
+ Prototype: unsigned short SLsmg_char_at(void);
+ Returns the character and its attributes object number at the current
+ cursor position.
+2Variables
+ SLsmg_Tab_Width (Default is 8).
+
+1Searching-Functions
+ The S-Lang library incorporates two types of searches: Regular expression
+ pattern matching and ordinary searching.
+2Regular-Expressions
+
+ !!! No documentation available yet !!!
+
+2Simple-Searches
+ The routines for ordinary searching are defined in the `slsearch.c' file.
+ To use these routines, simply include "slang.h" in your program and simply
+ call the appropriate routines.
+
+ The searches can go in either a forward or backward direction and can
+ either be case or case insensitive. The region that is searched may
+ contain null characters (ASCII 0) however, the search string cannot in the
+ current implementation. In addition the length of the string to be found
+ is currently limited to 256 characters.
+
+ Before searching, the function `SLsearch_init' must first be called to
+ ``preprocess'' the search string.
+3initialization
+ The function `SLsearch_init' must be called before a search can take place.
+ Its prototype is:
+
+ int SLsearch_init (char *key, int dir, int case_sens, SLsearch_Type *st);
+
+ Here `key' is the string to be searched for. `dir' specifies the direction
+ of the search: a value greater than zero is used for searching forward and
+ a value less than zero is used for searching backward. The parameter
+ `case_sens' specifies whether the search is case sensitive or not. A
+ non-zero value indicates that case is important. `st' is a pointer to a
+ structure of type `SLsearch_Type' defined in "slang.h". This structure is
+ initialized by this routine and must be passed to `SLsearch' when the
+ search is actually performed.
+
+ This routine returns the length of the string to be searched for.
+
+3SLsearch
+ Prototype: unsigned char *SLsearch (unsigned char *pmin, unsigned char *pmax,
+ SLsearch_Type *st);
+
+ This function performs the search defined by a previous call to
+ `SLsearch_init' over a region specified by the pointers `pmin' and `pmax'.
+
+ It returns a pointer to the start of the match if successful or it will
+ return NULL if a match was not found.
+
+
diff --git a/libslang/doc/OLD/help/slhelp.c b/libslang/doc/OLD/help/slhelp.c
new file mode 100644
index 0000000..be7638f
--- /dev/null
+++ b/libslang/doc/OLD/help/slhelp.c
@@ -0,0 +1,587 @@
+#include "config.h"
+
+#include <stdio.h>
+
+#ifdef unix
+# include <signal.h>
+#endif
+
+#include "slang.h"
+#include "jdmacros.h"
+
+#ifndef HELP_DIR
+#define HELP_DIR ""
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+
+typedef struct SLhlp_Node_Type
+{
+ char *name;
+ struct SLhlp_Node_Type *child;
+ struct SLhlp_Node_Type *sister;
+ unsigned long pos;
+} SLhlp_Node_Type;
+
+typedef struct
+{
+ FILE *fp;
+ SLhlp_Node_Type *root;
+ SLhlp_Node_Type *sub; /* current subtopic node */
+ SLhlp_Node_Type *now; /* Node we are currently reading from */
+ SLhlp_Node_Type *path[10]; /* path to current node */
+ int level;
+} SLhlp_File_Type;
+
+#define MAX_HELP_FILES 10
+
+SLhlp_File_Type Help_Files[MAX_HELP_FILES];
+
+
+static int add_level (int level, int fd, char *name, unsigned long pos)
+{
+ SLhlp_Node_Type *node, *parent, *new_node;
+ int len;
+
+ while (*name == ' ') name++;
+ len = strlen(name);
+
+ if (len) while (name[len - 1] == ' ') len--;
+ if (len == 0) return -1;
+ name[len] = 0;
+
+ parent = node = Help_Files[fd].root;
+ while (level-- > 0)
+ {
+ if (node == NULL)
+ {
+ return -1;
+ }
+ while (node->sister != NULL) node = node->sister;
+ parent = node;
+ node = node->child;
+ }
+
+
+ if ((NULL == (new_node = (SLhlp_Node_Type *) SLMALLOC (sizeof (SLhlp_Node_Type))))
+ || (NULL == (new_node->name = (char *) SLMALLOC (len + 1))))
+ {
+ SLang_Error = SL_MALLOC_ERROR;
+ return -1;
+ }
+
+ new_node->sister = NULL;
+ new_node->child = NULL;
+ new_node->pos = pos;
+ strcpy (new_node->name, name);
+
+ if (node == NULL)
+ {
+ if (parent == NULL)
+ {
+ Help_Files[fd].root = new_node;
+ }
+ else parent->child = new_node;
+ }
+ else
+ {
+ while (node->sister != NULL) node = node->sister;
+ node->sister = new_node;
+ }
+ return 0;
+}
+
+
+static void free_nodes (SLhlp_Node_Type *node)
+{
+ if (node->child != NULL) free_nodes (node->child);
+ if (node->sister != NULL) free_nodes (node->sister);
+ if (node->name != NULL) SLFREE (node->name);
+ SLFREE (node);
+}
+
+
+
+static int check_fd (int fd)
+{
+ if (((fd >= MAX_HELP_FILES) || (fd < 0)) || (Help_Files[fd].fp == NULL))
+ {
+ if (SLang_Error == 0) SLang_Error = INTRINSIC_ERROR;
+ return 0;
+ }
+ return 1;
+}
+
+
+static void SLhlp_close_help (int fd)
+{
+ if (!check_fd (fd)) return;
+ fclose (Help_Files[fd].fp); Help_Files[fd].fp = NULL;
+ if (Help_Files[fd].root != NULL) free_nodes (Help_Files[fd].root);
+}
+
+
+static int SLhlp_open_help (char *file)
+{
+ int fd = 0, ch;
+ FILE *fp;
+ int level;
+ char topic[256], *b;
+ unsigned long pos;
+
+ while ((fd < MAX_HELP_FILES) && (Help_Files[fd].fp != NULL))
+ fd++;
+
+ if (fd == MAX_HELP_FILES) return -1;
+ if (NULL == (Help_Files[fd].fp = fp = fopen (file, "r"))) return -1;
+
+
+ while (1)
+ {
+ ch = getc (fp);
+
+ bypass_getc:
+
+ if ((ch > '9') || (ch == ' ')) continue;
+ if (ch == '\n')
+ {
+ ch = getc (fp);
+ if ((ch == ' ') || (ch > '9')) continue;
+ if (ch >= '1')
+ {
+ level = ch - '1';
+ pos = ftell (fp);
+ b = topic;
+ while (('\n' != (ch = getc (fp))) && (ch != EOF))
+ {
+ *b++ = ch;
+ }
+ *b = 0;
+ if (add_level (level, fd, topic, pos)) goto error;
+ }
+ goto bypass_getc;
+ }
+ if (ch == EOF) break;
+ }
+
+ Help_Files[fd].now = NULL;
+ Help_Files[fd].sub = Help_Files[fd].root;
+ Help_Files[fd].path[0] = NULL;
+
+ return fd;
+
+
+ error:
+ SLhlp_close_help (fd);
+ return -1;
+}
+
+static char *SLhlp_get_subtopic (int fd)
+{
+ SLhlp_Node_Type *node;
+
+ if (!check_fd(fd)) return NULL;
+ if ((node = Help_Files[fd].sub) == NULL) return NULL;
+
+ Help_Files[fd].sub = node->sister;
+ return node->name;
+}
+
+
+static char *SLhlp_gets (int fd, char *buf)
+{
+ SLhlp_Node_Type *node;
+ char ch;
+
+
+ if (!check_fd(fd)) return NULL;
+
+ node = Help_Files[fd].now;
+ if (node == NULL) return NULL;
+
+ if ((NULL == fgets(buf, 255, Help_Files[fd].fp))
+ || ((*buf <= '9') && (*buf >= '0')))
+ {
+ if ((node->child == NULL) && Help_Files[fd].level)
+ {
+ Help_Files[fd].level--;
+ }
+ Help_Files[fd].now = NULL;
+ return NULL;
+ }
+
+ /* First character is reserved. */
+ if (*buf > ' ')
+ {
+ ch = *buf | 0x20;
+ if ((ch < 'a') || (ch > 'z'))
+ {
+ *buf = '\n';
+ *(buf + 1) = 0;
+ }
+ }
+
+ return buf;
+}
+
+static int my_strncasecmp (char *a, char *b, int n)
+{
+ register char cha, chb;
+
+ while (n--)
+ {
+ cha = *a++;
+ chb = *b++;
+ if (cha != 0)
+ {
+ if ((cha == chb)
+ || ((cha | 0x20) == (chb | 0x20))) continue;
+ }
+ return cha - chb;
+ }
+ return 0;
+}
+
+
+
+static int SLhlp_select_topic (int fd, char *topic)
+{
+ char topic_buf[256];
+ char *t, ch;
+ int level = 0;
+ int len;
+
+ SLhlp_Node_Type *node, *parent;
+
+ if (!check_fd (fd)) return -1;
+
+ parent = node = Help_Files[fd].root;
+
+ ch = 0;
+ if (topic != NULL)
+ while (((ch = *topic) <= ' ') && ch) topic++;
+
+ if (ch != 0) while (node != NULL)
+ {
+ parent = node;
+ t = topic_buf;
+
+ while ((ch = *topic) > ' ')
+ {
+ *t++ = ch;
+ topic++;
+ }
+ while (((ch = *topic) <= ' ') && ch) topic++;
+ *t = 0;
+
+ len = strlen (topic_buf);
+
+
+ if (len) while (my_strncasecmp (node->name, topic_buf, len))
+ {
+ node = node->sister;
+ if (node == NULL) break;
+ }
+
+ if (node == NULL) break;
+ Help_Files[fd].path[level++] = node;
+ if ((ch == 0) || (ch == '\n')) break;
+ node = node -> child;
+ }
+
+ /* level comes out at 1 greater than last valid one */
+ Help_Files[fd].level = level;
+
+ if (node != NULL) /* success */
+ {
+ Help_Files[fd].sub = node->child;
+ Help_Files[fd].now = node;
+ fseek (Help_Files[fd].fp, node->pos, SEEK_SET);
+ return 0;
+ }
+ else /* failure */
+ {
+ Help_Files[fd].now = NULL;
+ Help_Files[fd].sub = parent;
+ return -1;
+ }
+}
+
+static int SLhlp_what_topic (int fd, char *buf)
+{
+ int level, i;
+ char *b;
+ if (!check_fd(fd)) return -1;
+
+ level = Help_Files[fd].level;
+ *buf = 0;
+ if (level == 0) return 0;
+
+ b = buf;
+ for (i = 0; i < level; i++)
+ {
+ strcpy (b, Help_Files[fd].path[i]->name);
+ b = b + strlen (b);
+ *b++ = ' ';
+ }
+ *(b - 1) = 0;
+ return level;
+}
+
+static int SLhlp_up_topic (int fd)
+{
+ if (!check_fd(fd)) return -1;
+
+ if (Help_Files[fd].level) Help_Files[fd].level--;
+ return 0;
+}
+
+
+
+
+/* --------------------------------------------------------------------- */
+
+static void cls (void)
+{
+ SLtt_cls ();
+ SLtt_flush_output ();
+}
+
+
+static void newline (int nl, int reset, int cls_flag)
+{
+ static int n;
+
+ if (nl) putc('\n', stdout);
+ n++;
+
+ if (n == SLtt_Screen_Rows - 1)
+ {
+ SLtt_reverse_video (1);
+ SLtt_write_string ("---Press RETURN to continue.---");
+ SLtt_normal_video ();
+ SLtt_flush_output ();
+
+ SLang_getkey ();
+ if (cls_flag) cls ();
+ else
+ fputs("\r \r", stdout);
+
+ cls_flag = 0;
+ n = 0;
+ }
+
+ if (reset)
+ {
+ n = 0;
+ if (cls_flag) cls ();
+ return;
+ }
+}
+
+SLang_RLine_Info_Type *Help_Rli;
+
+static SLang_RLine_Info_Type *init_readline (void)
+{
+ unsigned char *buf = NULL;
+ SLang_RLine_Info_Type *rli;
+
+ if ((NULL == (rli = (SLang_RLine_Info_Type *) SLMALLOC (sizeof(SLang_RLine_Info_Type))))
+ || (NULL == (buf = (unsigned char *) SLMALLOC (256))))
+ {
+ fprintf(stderr, "malloc error.\n");
+ exit(-1);
+ }
+
+ SLMEMSET ((char *) rli, 0, sizeof (SLang_RLine_Info_Type));
+ rli->buf = buf;
+ rli->buf_len = 255;
+ rli->tab = 8;
+ rli->dhscroll = 20;
+ rli->getkey = SLang_getkey;
+ rli->tt_goto_column = NULL;
+ rli->update_hook = NULL;
+
+ if (SLang_init_readline (rli) < 0)
+ {
+ fprintf(stderr, "Unable to initialize readline library.\n");
+ exit (-1);
+ }
+
+ return rli;
+}
+
+static char *hlp_get_input (char *prompt)
+{
+ int i;
+
+ if (Help_Rli == NULL)
+ {
+ Help_Rli = init_readline ();
+ Help_Rli->update_hook = NULL;
+ }
+
+ Help_Rli->edit_width = SLtt_Screen_Cols - 1;
+ Help_Rli->prompt = prompt;
+ *Help_Rli->buf = 0;
+
+
+ i = SLang_read_line (Help_Rli);
+
+ if ((i >= 0) && !SLang_Error && !SLKeyBoard_Quit)
+ {
+ SLang_rline_save_line (Help_Rli);
+ }
+ else return NULL;
+
+ return (char *) Help_Rli->buf;
+}
+
+
+static void do_subtopics (int fd)
+{
+ char *s;
+ int len, dlen;
+
+ if ((s = SLhlp_get_subtopic (fd)) != NULL)
+ {
+ len = 0;
+ newline (1, 0, 0);
+ fprintf(stdout, "Available Topics/Subtopics:");
+ newline (1, 0, 0);
+ newline (1, 0, 0);
+ do
+ {
+ dlen = strlen (s);
+ len += dlen;
+
+ if (len >= 80)
+ {
+ len = dlen;
+ newline (1, 0, 0);
+ }
+ fputs(s, stdout);
+ dlen = 21 - len % 20;
+ len += dlen;
+ if (len < 80)
+ {
+ while (dlen--) putc(' ', stdout);
+ }
+ }
+ while (NULL != (s = SLhlp_get_subtopic(fd)));
+ newline (1, 0, 0);
+ }
+}
+
+static void get_screen_size (int sig)
+{
+ SLtt_get_screen_size ();
+#ifdef SIGWINCH
+ signal (SIGWINCH, get_screen_size);
+#endif
+}
+
+
+
+int main (int argc, char **argv)
+{
+ char *buf, *file;
+ char buffer[256];
+ static int fd = -1;
+ int len;
+
+ if (argc != 2)
+ {
+ fprintf(stderr, "Usage: slhelp HELP-FILE\n");
+ exit (-1);
+ }
+
+ file = argv[1];
+ if (fd < 0) fd = SLhlp_open_help (file);
+ if (fd < 0)
+ {
+ fprintf (stderr, "Unable to open help file %s\n", file);
+ exit (-1);
+ }
+
+ SLang_init_tty (7, 1, 1);
+ SLtt_get_terminfo ();
+ SLtt_init_video ();
+ SLtt_Use_Ansi_Colors = 0;
+
+#ifdef SIGWINCH
+ signal (SIGWINCH, get_screen_size);
+#endif
+
+ get_screen_size (0);
+ cls ();
+
+ fputs ("\n\nSimply press RETURN at the 'Topic>' prompt to quit help.\n\n",
+ stdout);
+
+ if (SLhlp_what_topic (fd, buffer) > 0)
+ {
+ SLhlp_select_topic (fd, buffer);
+ }
+
+ while (1)
+ {
+ while (1)
+ {
+ if (SLhlp_what_topic (fd, buffer) <= 0)
+ {
+ SLhlp_select_topic (fd, "?");
+ *buffer = 0;
+ }
+ do_subtopics (fd);
+
+ len = strlen (buffer);
+ if (len) strcat (buffer, " Subtopic> ");
+ else strcpy (buffer, "Topic> ");
+ newline (1, 1, 0);
+
+ if (NULL == (buf = hlp_get_input (buffer)))
+ {
+ SLang_Error = 0;
+ if (SLKeyBoard_Quit)
+ {
+ SLKeyBoard_Quit = 0;
+ continue;
+ }
+ goto the_return;
+ }
+
+ if ((*buf == '\n') || (*buf == 0))
+ {
+ if (len == 0) goto the_return;
+ SLhlp_up_topic (fd);
+ continue;
+ }
+
+ buffer[len] = ' '; /* kill prompt */
+ strcpy (buffer + (len + 1), buf);
+ break;
+ }
+
+ newline (1, 1, 1);
+ if (-1 == SLhlp_select_topic (fd, buffer))
+ {
+ fprintf(stdout, "No help available on: %s", buf);
+ newline (1, 0, 0);
+ }
+ else while (NULL != SLhlp_gets (fd, buffer))
+ {
+ fputs(buffer, stdout);
+ newline (0, 0, 1);
+ }
+ }
+
+ the_return:
+
+ SLtt_reset_video ();
+ SLang_reset_tty ();
+ return 0;
+}
diff --git a/libslang/doc/README b/libslang/doc/README
new file mode 100644
index 0000000..32612e8
--- /dev/null
+++ b/libslang/doc/README
@@ -0,0 +1,25 @@
+The documentation here is provided in text format. Documentation in
+SGML, HTML, TeX, and postscript formats are also available from
+ftp://space.mit.edu/pub/davis/slang/slang-doc.tar.gz as well as the
+mirror sites. In addition, the documentation is available on-line from
+http://space.mit.edu/%7Edavis/slang-doc.html.
+
+The text subdirectory contains:
+
+ text/slang.txt Documentation describing the slang language
+ text/cslang.txt C programmer's guide to the library
+ text/cref.txt Reference Manual for the C functions
+ text/slangfun.txt Reference Manual for the slang intrinsic functions
+
+There may be additional subdirectories:
+
+ tm/ Text-Macro source for documentation
+ html/ Documentation in HTML form
+ text/ Documentation in text form
+ ps/ Documentation in postscript (from LaTeX)
+ sgml/ SGML source
+
+The documentation was created by SGML-Tools from SGML format, which
+itself was created from text-macro source. The LaTeX2e output
+produced by SGML-Tools needs some additional tweaking by the script
+tm/fixtex.sl.
diff --git a/libslang/doc/grammar.txt b/libslang/doc/grammar.txt
new file mode 100644
index 0000000..0c69b37
--- /dev/null
+++ b/libslang/doc/grammar.txt
@@ -0,0 +1,131 @@
+This grammar was derived from slparse.c
+
+statement:
+ compound-statement
+ if ( expression ) statement
+ if ( expression ) statement else statement
+ !if ( expression ) statement
+ loop ( expression ) statement
+ _for ( expression ) statement
+ while ( expression ) statement
+ do statement while (expression) ;
+ for ( expressionopt ; expressionopt ; expressionopt ) statement
+ ERROR_BLOCK statement
+ EXIT_BLOCK statement
+ USER_BLOCK0 statement
+ USER_BLOCK1 statement
+ USER_BLOCK2 statement
+ USER_BLOCK3 statement
+ USER_BLOCK4 statement
+ forever statement
+ break ;
+ continue ;
+ return expressionopt ;
+ variable variable-list ;
+ struct struct-decl ;
+ define identifier function-args ;
+ define identifier function-args compound-statement
+ switch ( expression ) statement
+ rpn-line
+ at-line
+ push ( expression )
+ ( expression ) = expression ;
+ expression ;
+ expression :
+
+
+
+statement-list:
+ statement
+ statement-list statement
+
+
+compound-statement:
+ { statement-list }
+
+
+variable-list:
+ variable-decl
+ variable-decl variable-list
+
+variable-decl:
+ identifier
+ identifier = simple-expression
+
+
+struct-declaration:
+ struct { struct-field-list };
+
+struct-field-list:
+ struct-field-name , struct-field-list
+ struct-field-name
+
+struct-declaration:
+ typedef struct { struct-field-list } Type_Name;
+
+struct-field-list:
+ struct-field-name , struct-field-list
+ struct-field-name
+
+function-args:
+ ( args-dec-opt )
+
+args-decl-opt:
+ identifier
+ args-decl , identifier
+
+expression:
+ simple_expression
+ simple-expression , expression
+ <none>
+
+
+% Note: simple-expression groups operators OP1 at same level. The
+% actual implementation will not do this.
+simple-expression:
+ unary-expression
+ binary-expression BINARY-OP unary-expression
+ andelse xxelse-expression-list
+ orelse xxelse-expression-list
+
+xxelse-expression-list:
+ { expression }
+ xxelse-expression-list { expression }
+binary-expression:
+ unary-expression
+ unary-expression BINARY-OP binary-expression
+
+unary-expression:
+ postfix-expression
+ ++ postfix-expression
+ -- postfix-expression
+ case unary-expression
+ OP3 unary-expression
+ (OP3: + - ~ & not @)
+
+postfix-expression:
+ primary-expression
+ postfix-expression [ expression ]
+ postfix-expression ( function-args-expression )
+ postfix-expression . identifier
+ postfix-expression ^ unary-expression
+ postfix-expression ++
+ postfix-expression --
+ postfix-expression = simple-expression
+ postfix-expression += simple-expression
+ postfix-expression -= simple-expression
+
+primary-expression:
+ literal
+ identifier
+ ( expression_opt )
+ [ inline-array-expression ]
+ &identifier
+ struct-definition
+ __tmp(literal)
+
+inline-array-expression:
+ expression
+ expression : expression
+ expression : expression : expression
+
diff --git a/libslang/doc/internal/rpn.txt b/libslang/doc/internal/rpn.txt
new file mode 100644
index 0000000..e613021
--- /dev/null
+++ b/libslang/doc/internal/rpn.txt
@@ -0,0 +1,60 @@
+Variable Assignment:
+ x = --> =x
+ x += --> +=x
+ x -= --> -=x
+ x++ --> ++x
+ x-- --> --x
+ Note: The current version of slang does not distguish between the
+ post and pre-increment operators. A future version may make a
+ distinction and assignment statements may return a value.
+
+
+Function Definition: define f (arg1, ..., argN) { statements }
+ --> ( [ arg1 arg2 ... argN ] =argN ... =arg1 rpn-statements ) f
+
+Variable Declaration: variable x1, ... xN;
+ --> [ x1 ... xN ]
+
+Structure Definition: struct {f1, ... fN}
+ --> "f1" ... "fN" N struct
+
+Structure Typedef: typedef struct { f1, ... fN } Type_Name ;
+ --> __typedef f1 ... fN ] "Type_Name"
+
+Multiple Assignment Expression: (x1, ..., xN) = expression
+ --> rpn-expression =xN ... =x1
+ Note: If xj is missing, it will be replaced by `pop'
+
+Function call: f (x1, ..., xN)
+ --> __arg x1 ... xN __earg f
+ Note: if xj is missing, it will be replaced by NULL
+
+Array reference: X [x1, .., xN]
+ --> __arg x1 ... xN X __aget
+ Note: __earg is implicit
+
+Array assignment: X [x1, ... xN] ASSIGNMENT-OP
+ --> __arg x1 ... xN X RPN-ASSIGNMENT-OP
+ ASSIGNMENT-OP:
+ = --> __aput
+ ++ --> __aput_plusplus
+ -- --> __aput_minusminus
+ += --> __aput_pluseqs
+ -= --> __aput_minuseqs
+ Note: __earg is implicit
+
+Structure Reference: X.a --> "a" X .
+
+Structure Assignment: X.a ASSIGNMENT-OP expression;
+ --> rpn-expression "a" X RPN-ASSIGNMENT-OP
+ ASSIGNMENT-OP --> RPN-ASSIGNMENT-OP:
+ = --> __struct_eqs
+ += --> __struct_pluseqs
+ -= --> __struct_minuseqs
+ -- --> __struct_minusminus
+ ++ --> __struct_plusplus
+
+Variable Alias: &x --> __alias x
+
+foreach (X) using (Y,...) block
+ --> X __arg Y... __earg { block } foreach
diff --git a/libslang/doc/slangdoc.html b/libslang/doc/slangdoc.html
new file mode 100644
index 0000000..97ef431
--- /dev/null
+++ b/libslang/doc/slangdoc.html
@@ -0,0 +1,27 @@
+<!doctype html public "-//ietf//dtd html 2.0//en">
+<html>
+<title>Index</title>
+<body>
+
+The slang documentation available online from
+<a href="http://www.s-lang.org/docs.html">
+http://www.s-lang.org/docs.html</a>.<p>
+
+The entire documentation (HTML, SGML, text, postscript, and
+text-macro formats) is also available for download from
+<a href="ftp://space.mit.edu/pub/davis/slang/">
+ftp://space.mit.edu/pub/davis/slang/</a><p>
+
+If you have downloaded the above file, then the following local links should
+work:<p>
+
+<a href="html/slang.html">A Guide to the S-Lang Language</a><p>
+
+<a href="html/cslang.html">S-Lang Library Programmer's Guide</a><p>
+
+<a href="html/slangfun.html">Intrinsic Function Reference</a><p>
+
+<a href="html/cref.html">C Library Reference</a><p>
+
+</body>
+</html>
diff --git a/libslang/doc/text/cref.txt b/libslang/doc/text/cref.txt
new file mode 100644
index 0000000..fca54da
--- /dev/null
+++ b/libslang/doc/text/cref.txt
@@ -0,0 +1,4870 @@
+SLsmg_fill_region
+
+ SYNOPSIS
+ Fill a rectangular region with a character
+
+ USAGE
+ void SLsmg_fill_region (r, c, nr, nc, ch)
+
+ int r
+ int c
+ unsigned int nr
+ unsigned int nc
+ unsigned char ch
+
+
+ DESCRIPTION
+ The `SLsmg_fill_region' function may be used to a
+ rectangular region with the character `ch' in the current color.
+ The rectangle's upper left corner is at row `r' and column
+ `c', and spans `nr' rows and `nc' columns. The position
+ of the virtual cursor will be left at (`r', `c').
+
+ SEE ALSO
+ SLsmg_write_char, SLsmg_set_color
+--------------------------------------------------------------
+
+SLsmg_set_char_set
+
+ SYNOPSIS
+ Turn on or off line drawing characters
+
+ USAGE
+ void SLsmg_set_char_set (int a);
+
+ DESCRIPTION
+ `SLsmg_set_char_set' may be used to select or deselect the line drawing
+ character set as the current character set. If `a' is non-zero,
+ the line drawing character set will be selected. Otherwise, the
+ standard character set will be selected.
+
+ NOTES
+ There is no guarantee that this function will actually enable the
+ use of line drawing characters. All it does is cause subsequent
+ characters to be rendered using the terminal's alternate character
+ set. Such character sets usually contain line drawing characters.
+
+ SEE ALSO
+ SLsmg_write_char, SLtt_get_terminfo
+--------------------------------------------------------------
+
+int SLsmg_Scroll_Hash_Border;
+
+ SYNOPSIS
+ Set the size of the border for the scroll hash
+
+ USAGE
+ int SLsmg_Scroll_Hash_Border = 0;
+
+ DESCRIPTION
+ This variable may be used to ignore the characters that occur at the
+ beginning and the end of a row when performing the hash calculation
+ to determine whether or not a line has scrolled. The default value
+ is zero which means that all the characters on a line will be used.
+
+ SEE ALSO
+ SLsmg_refresh
+--------------------------------------------------------------
+
+SLsmg_suspend_smg
+
+ SYNOPSIS
+ Suspend screen management
+
+ USAGE
+ int SLsmg_suspend_smg (void)
+
+ DESCRIPTION
+ `SLsmg_suspend_smg' can be used to suspend the state of the
+ screen management facility during suspension of the program. Use of
+ this function will reset the display back to its default state. The
+ funtion `SLsmg_resume_smg' should be called after suspension.
+
+ It returns zero upon success, or -1 upon error.
+
+ This function is similar to `SLsmg_reset_smg' except that the
+ state of the display prior to calling `SLsmg_suspend_smg' is saved.
+
+ SEE ALSO
+ SLsmg_resume_smg, SLsmg_reset_smg
+--------------------------------------------------------------
+
+SLsmg_resume_smg
+
+ SYNOPSIS
+ Resume screen management
+
+ USAGE
+ int SLsmg_resume_smg (void)
+
+ DESCRIPTION
+ `SLsmg_resume_smg' should be called after
+ `SLsmg_suspend_smg' to redraw the display exactly like it was
+ before `SLsmg_suspend_smg' was called. It returns zero upon
+ success, or -1 upon error.
+
+ SEE ALSO
+ SLsmg_suspend_smg
+--------------------------------------------------------------
+
+SLsmg_erase_eol
+
+ SYNOPSIS
+ Erase to the end of the row
+
+ USAGE
+ void SLsmg_erase_eol (void);
+
+ DESCRIPTION
+ `SLsmg_erase_eol' erases all characters from the current
+ position to the end of the line. The newly created space is given
+ the color of the current color. This function has no effect on the
+ position of the virtual cursor.
+
+ SEE ALSO
+ SLsmg_gotorc, SLsmg_erase_eos, SLsmg_fill_region
+--------------------------------------------------------------
+
+SLsmg_gotorc
+
+ SYNOPSIS
+ Move the virtual cursor
+
+ USAGE
+ void SLsmg_gotorc (int r, int c)
+
+ DESCRIPTION
+ The `SLsmg_gotorc' function moves the virtual cursor to the row
+ `r' and column `c'. The first row and first column is
+ specified by `r = 0' and `c = 0'.
+
+ SEE ALSO
+ SLsmg_refresh
+--------------------------------------------------------------
+
+SLsmg_erase_eos
+
+ SYNOPSIS
+ Erase to the end of the screen
+
+ USAGE
+ void SLsmg_erase_eos (void);
+
+ DESCRIPTION
+ The `SLsmg_erase_eos' is like `SLsmg_erase_eol' except that
+ it erases all text from the current position to the end of the
+ display. The current color will be used to set the background of
+ the erased area.
+
+ SEE ALSO
+ SLsmg_erase_eol
+--------------------------------------------------------------
+
+SLsmg_reverse_video
+
+ SYNOPSIS
+ Set the current color to 1
+
+ USAGE
+ void SLsmg_reverse_video (void);
+
+ DESCRIPTION
+ This function is nothing more than `SLsmg_set_color(1)'.
+
+ SEE ALSO
+ SLsmg_set_color
+--------------------------------------------------------------
+
+SLsmg_set_color (int)
+
+ SYNOPSIS
+ Set the current color
+
+ USAGE
+ void SLsmg_set_color (int c);
+
+ DESCRIPTION
+ `SLsmg_set_color' is used to set the current color. The
+ parameter `c' is really a color object descriptor. Actual
+ foreground and background colors as well as other visual attributes
+ may be associated with a color descriptor via the
+ `SLtt_set_color' function.
+
+ EXAMPLE
+ This example defines color `7' to be green foreground on black
+ background and then displays some text in this color:
+
+ SLtt_set_color (7, NULL, "green", "black");
+ SLsmg_set_color (7);
+ SLsmg_write_string ("Hello");
+ SLsmg_refresh ();
+
+
+ NOTES
+ It is important to understand that the screen managment routines
+ know nothing about the actual colors associated with a color
+ descriptor. Only the descriptor itself is used by the `SLsmg'
+ routines. The lower level `SLtt' interface converts the color
+ descriptors to actual colors. Thus
+
+ SLtt_set_color (7, NULL, "green", "black");
+ SLsmg_set_color (7);
+ SLsmg_write_string ("Hello");
+ SLtt_set_color (7, NULL, "red", "blue");
+ SLsmg_write_string ("World");
+ SLsmg_refresh ();
+
+ will result in `"hello"' displayed in red on blue and _not_
+ green on black.
+
+ SEE ALSO
+ SLtt_set_color, SLtt_set_color_object
+--------------------------------------------------------------
+
+SLsmg_normal_video
+
+ SYNOPSIS
+ Set the current color to 0
+
+ USAGE
+ void SLsmg_normal_video (void);
+
+ DESCRIPTION
+ `SLsmg_normal_video' sets the current color descriptor to `0'.
+
+ SEE ALSO
+ SLsmg_set_color
+--------------------------------------------------------------
+
+SLsmg_printf
+
+ SYNOPSIS
+ Format a string on the virtual display
+
+ USAGE
+ void SLsmg_printf (char *fmt, ...)
+
+ DESCRIPTION
+ `SLsmg_printf' format a `printf' style variable argument
+ list and writes it on the virtual display. The virtual cursor will
+ be moved to the end of the string.
+
+ SEE ALSO
+ SLsmg_write_string, SLsmg_vprintf
+--------------------------------------------------------------
+
+SLsmg_vprintf
+
+ SYNOPSIS
+ Format a string on the virtual display
+
+ USAGE
+ void SLsmg_vprintf (char *fmt, va_list ap)
+
+ DESCRIPTION
+ `SLsmg_vprintf' formats a string in the manner of _vprintf_
+ and writes the result to the display. The virtual cursor is
+ advanced to the end of the string.
+
+ SEE ALSO
+ SLsmg_write_string, SLsmg_printf
+--------------------------------------------------------------
+
+SLsmg_write_string
+
+ SYNOPSIS
+ Write a character string on the display
+
+ USAGE
+ void SLsmg_write_string (char *s)
+
+ DESCRIPTION
+ The function `SLsmg_write_string' displays the string `s' on
+ the virtual display at the current position and moves the position
+ to the end of the string.
+
+ SEE ALSO
+ SLsmg_printf, SLsmg_write_nstring
+--------------------------------------------------------------
+
+SLsmg_write_nstring
+
+ SYNOPSIS
+ Write the first n characters of a string on the display
+
+ USAGE
+ void SLsmg_write_nstring (char *s, unsigned int n);
+
+ DESCRIPTION
+ `SLsmg_write_nstring' writes the first `n' characters of
+ `s' to this virtual display. If the length of the string
+ `s' is less than `n', the spaces will used until
+ `n' characters have been written. `s' can be `NULL', in
+ which case `n' spaces will be written.
+
+ SEE ALSO
+ SLsmg_write_string, SLsmg_write_nchars
+--------------------------------------------------------------
+
+SLsmg_write_char
+
+ SYNOPSIS
+ Write a character to the virtual display
+
+ USAGE
+ void SLsmg_write_char (char ch);
+
+ DESCRIPTION
+ `SLsmg_write_char' writes the character `ch' to the virtual
+ display.
+
+ SEE ALSO
+ SLsmg_write_nchars, SLsmg_write_string
+--------------------------------------------------------------
+
+SLsmg_write_nchars
+
+ SYNOPSIS
+ Write n characters to the virtual display
+
+ USAGE
+ void SLsmg_write_nchars (char *s, unsigned int n);
+
+ DESCRIPTION
+ `SLsmg_write_nchars' writes at most `n' characters from the
+ string `s' to the display. If the length of `s' is less
+ than `n', the whole length of the string will get written.
+
+ This function differs from `SLsmg_write_nstring' in that
+ `SLsmg_write_nstring' will pad the string to write exactly
+ `n' characters. `SLsmg_write_nchars' does not perform any
+ padding.
+
+ SEE ALSO
+ SLsmg_write_nchars, SLsmg_write_nstring
+--------------------------------------------------------------
+
+SLsmg_write_wrapped_string
+
+ SYNOPSIS
+ Write a string to the display with wrapping
+
+ USAGE
+ void SLsmg_write_wrapped_string (s, r, c, nr, nc, fill)
+
+ char *s
+ int r, c
+ unsigned int nr, nc
+ int fill
+
+
+ DESCRIPTION
+ `SLsmg_write_wrapped_string' writes the string `s' to the
+ virtual display. The string will be confined to the rectangular
+ region whose upper right corner is at row `r' and column `c',
+ and consists of `nr' rows and `nc' columns. The string will
+ be wrapped at the boundaries of the box. If `fill' is non-zero,
+ the last line to which characters have been written will get padded
+ with spaces.
+
+ NOTES
+ This function does not wrap on word boundaries. However, it will
+ wrap when a newline charater is encountered.
+
+ SEE ALSO
+ SLsmg_write_string
+--------------------------------------------------------------
+
+SLsmg_cls
+
+ SYNOPSIS
+ Clear the virtual display
+
+ USAGE
+ void SLsmg_cls (void)
+
+ DESCRIPTION
+ `SLsmg_cls' erases the virtual display using the current color.
+ This will cause the physical display to get cleared the next time
+ `SLsmg_refresh' is called.
+
+ NOTES
+ This function is not the same as
+
+ SLsmg_gotorc (0,0); SLsmg_erase_eos ();
+
+ since these statements do not guarantee that the physical screen
+ will get cleared.
+
+ SEE ALSO
+ SLsmg_refresh, SLsmg_erase_eos
+--------------------------------------------------------------
+
+SLsmg_refresh
+
+ SYNOPSIS
+ Update physical screen
+
+ USAGE
+ void SLsmg_refresh (void)
+
+ DESCRIPTION
+ The `SLsmg_refresh' function updates the physical display to
+ look like the virtual display.
+
+ SEE ALSO
+ SLsmg_suspend_smg, SLsmg_init_smg, SLsmg_reset_smg
+--------------------------------------------------------------
+
+SLsmg_touch_lines
+
+ SYNOPSIS
+ Mark lines on the virtual display for redisplay
+
+ USAGE
+ void SLsmg_touch_lines (int r, unsigned int nr)
+
+ DESCRIPTION
+ `SLsmg_touch_lines' marks the `nr' lines on the virtual
+ display starting at row `r' for redisplay upon the next call to
+ `SLsmg_refresh'.
+
+ NOTES
+ This function should rarely be called, if ever. If you find that
+ you need to call this function, then your application should be
+ modified to properly use the `SLsmg' screen management routines.
+ This function is provided only for curses compatibility.
+
+ SEE ALSO
+ SLsmg_refresh
+--------------------------------------------------------------
+
+SLsmg_init_smg
+
+ SYNOPSIS
+ Initialize the var{SLsmg
+
+ USAGE
+ int SLsmg_init_smg (void)
+
+ DESCRIPTION
+ The `SLsmg_init_smg' function initializes the `SLsmg' screen
+ management routines. Specifically, this function allocates space
+ for the virtual display and calls `SLtt_init_video' to put the
+ terminal's physical display in the proper state. It is up to the
+ caller to make sure that the `SLtt' routines are initialized via
+ `SLtt_get_terminfo' before calling `SLsmg_init_smg'.
+
+ This function should also be called any time the size of the
+ physical display has changed so that it can reallocate a new virtual
+ display to match the physical display.
+
+ It returns zero upon success, or -1 upon failure.
+
+ SEE ALSO
+ SLsmg_reset_smg
+--------------------------------------------------------------
+
+SLsmg_reset_smg
+
+ SYNOPSIS
+ Reset the var{SLsmg
+
+ USAGE
+ int SLsmg_reset_smg (void);
+
+ DESCRIPTION
+ `SLsmg_reset_smg' resets the `SLsmg' screen management
+ routines by freeing all memory allocated while it was active. It
+ also calls `SLtt_reset_video' to put the terminal's display in
+ it default state.
+
+ SEE ALSO
+ SLsmg_init_smg
+--------------------------------------------------------------
+
+SLsmg_char_at
+
+ SYNOPSIS
+ Get the character at the current position on the virtual display
+
+ USAGE
+ unsigned short SLsmg_char_at(void)
+
+ DESCRIPTION
+ The `SLsmg_char_at' function returns the character and its color
+ at the current position on the virtual display.
+
+ SEE ALSO
+ SLsmg_read_raw, SLsmg_write_char
+--------------------------------------------------------------
+
+SLsmg_set_screen_start
+
+ SYNOPSIS
+ Set the origin of the virtual display
+
+ USAGE
+ void SLsmg_set_screen_start (int *r, int *c)
+
+ DESCRIPTION
+ `SLsmg_set_screen_start' sets the origin of the virtual display
+ to the row `*r' and the column `*c'. If either `r' or `c'
+ is `NULL', then the corresponding value will be set to `0'.
+ Otherwise, the location specified by the pointers will be updated to
+ reflect the old origin.
+
+ See \tt{slang/demo/pager.c} for how this function may be used to
+ scroll horizontally.
+
+ SEE ALSO
+ SLsmg_init_smg
+--------------------------------------------------------------
+
+SLsmg_draw_hline
+
+ SYNOPSIS
+ Draw a horizontal line
+
+ USAGE
+ void SLsmg_draw_hline (unsigned int len)
+
+ DESCRIPTION
+ The `SLsmg_draw_hline' function draws a horizontal line of
+ length `len' on the virtual display. The position of the
+ virtual cursor is left at the end of the line.
+
+ SEE ALSO
+ SLsmg_draw_vline
+--------------------------------------------------------------
+
+SLsmg_draw_vline
+
+ SYNOPSIS
+ Draw a vertical line
+
+ USAGE
+ void SLsmg_draw_vline (unsigned int len);
+
+ DESCRIPTION
+ The `SLsmg_draw_vline' function draws a vertical line of
+ length `len' on the virtual display. The position of the
+ virtual cursor is left at the end of the line.
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLsmg_draw_object
+
+ SYNOPSIS
+ Draw an object from the alternate character set
+
+ USAGE
+ void SLsmg_draw_object (int r, int c, unsigned char obj)
+
+ DESCRIPTION
+ The `SLsmg_draw_object' function may be used to place the object
+ specified by `obj' at row `r' and column `c'. The
+ object is really a character from the alternate character set and
+ may be specified using one of the following constants:
+
+ SLSMG_HLINE_CHAR Horizontal line
+ SLSMG_VLINE_CHAR Vertical line
+ SLSMG_ULCORN_CHAR Upper left corner
+ SLSMG_URCORN_CHAR Upper right corner
+ SLSMG_LLCORN_CHAR Lower left corner
+ SLSMG_LRCORN_CHAR Lower right corner
+ SLSMG_CKBRD_CHAR Checkboard character
+ SLSMG_RTEE_CHAR Right Tee
+ SLSMG_LTEE_CHAR Left Tee
+ SLSMG_UTEE_CHAR Up Tee
+ SLSMG_DTEE_CHAR Down Tee
+ SLSMG_PLUS_CHAR Plus or Cross character
+
+
+ SEE ALSO
+ SLsmg_draw_vline, SLsmg_draw_hline, SLsmg_draw_box
+--------------------------------------------------------------
+
+SLsmg_draw_box
+
+ SYNOPSIS
+ Draw a box on the virtual display
+
+ USAGE
+ void SLsmg_draw_box (int r, int c, unsigned int dr, unsigned int dc)
+
+ DESCRIPTION
+ `SLsmg_draw_box' uses the `SLsmg_draw_hline' and
+ `SLsmg_draw_vline' functions to draw a rectangular box on the
+ virtual display. The box's upper left corner is placed at row
+ `r' and column `c'. The width and length of the box is
+ specified by `dc' and `dr', respectively.
+
+ SEE ALSO
+ SLsmg_draw_vline, SLsmg_draw_hline, SLsmg_draw_object
+--------------------------------------------------------------
+
+SLsmg_set_color_in_region
+
+ SYNOPSIS
+ Change the color of a specifed region
+
+ USAGE
+ void SLsmg_set_color_in_region (color, r, c, dr, dc)
+
+ int color;
+ int r, c;
+ unsigned int dr, dc;
+
+
+ DESCRIPTION
+ `SLsmg_set_color_in_region' may be used to change the color of a
+ rectangular region whose upper left corner is given by
+ (`r',`c'), and whose width and height is given by `dc'
+ and `dr', respectively. The color of the region is given by the
+ `color' parameter.
+
+ SEE ALSO
+ SLsmg_draw_box, SLsmg_set_color
+--------------------------------------------------------------
+
+SLsmg_get_column
+
+ SYNOPSIS
+ Get the column of the virtual cursor
+
+ USAGE
+ int SLsmg_get_column(void);
+
+ DESCRIPTION
+ The `SLsmg_get_column' function returns the current column of
+ the virtual cursor on the virtual display.
+
+ SEE ALSO
+ SLsmg_get_row, SLsmg_gotorc
+--------------------------------------------------------------
+
+SLsmg_get_row
+
+ SYNOPSIS
+ Get the row of the virtual cursor
+
+ USAGE
+ int SLsmg_get_row(void);
+
+ DESCRIPTION
+ The `SLsmg_get_row' function returns the current row of the
+ virtual cursor on the virtual display.
+
+ SEE ALSO
+ SLsmg_get_column, SLsmg_gotorc
+--------------------------------------------------------------
+
+SLsmg_forward
+
+ SYNOPSIS
+ Move the virtual cursor forward n columns
+
+ USAGE
+ void SLsmg_forward (int n);
+
+ DESCRIPTION
+ The `SLsmg_forward' function moves the virtual cursor forward
+ `n' columns.
+
+ SEE ALSO
+ SLsmg_gotorc
+--------------------------------------------------------------
+
+SLsmg_write_color_chars
+
+ SYNOPSIS
+ Write characters with color descriptors to virtual display
+
+ USAGE
+ void SLsmg_write_color_chars (unsigned short *s, unsigned int len)
+
+ DESCRIPTION
+ The `SLsmg_write_color_chars' function may be used to write
+ `len' characters, each with a different color descriptor to the
+ virtual display. Each character and its associated color are
+ encoded as an `unsigned short' such that the lower eight bits
+ form the character and the next eight bits form the color.
+
+ SEE ALSO
+ SLsmg_char_at, SLsmg_write_raw
+--------------------------------------------------------------
+
+SLsmg_read_raw
+
+ SYNOPSIS
+ Read characters from the virtual display
+
+ USAGE
+ unsigned int SLsmg_read_raw (unsigned short *buf, unsigned int len)
+
+ DESCRIPTION
+ `SLsmg_read_raw' attempts to read `len' characters from the
+ current position on the virtual display into the buffer specified by
+ `buf'. It returns the number of characters actually read. This
+ number will be less than `len' if an attempt is made to read
+ past the right margin of the display.
+
+ NOTES
+ The purpose of the pair of functions, `SLsmg_read_raw' and
+ `SLsmg_write_raw', is to permit one to copy the contents of one
+ region of the virtual display to another region.
+
+ SEE ALSO
+ SLsmg_char_at, SLsmg_write_raw
+--------------------------------------------------------------
+
+SLsmg_write_raw
+
+ SYNOPSIS
+ Write characters directly to the virtual display
+
+ USAGE
+ unsigned int SLsmg_write_raw (unsigned short *buf, unsigned int len)
+
+ DESCRIPTION
+ The `SLsmg_write_raw' function attempts to write `len'
+ characters specified by `buf' to the display at the current
+ position. It returns the number of characters successfully written,
+ which will be less than `len' if an attempt is made to write
+ past the right margin.
+
+ NOTES
+ The purpose of the pair of functions, `SLsmg_read_raw' and
+ `SLsmg_write_raw', is to permit one to copy the contents of one
+ region of the virtual display to another region.
+
+ SEE ALSO
+ SLsmg_read_raw
+--------------------------------------------------------------
+
+SLallocate_load_type
+
+ SYNOPSIS
+ Allocate a SLang_Load_Type object
+
+ USAGE
+ SLang_Load_Type *SLallocate_load_type (char *name)
+
+ DESCRIPTION
+ The `SLallocate_load_type' function allocates and initializes
+ space for a `SLang_Load_Type' object and returns it. Upon
+ failure, the function returns `NULL'. The parameter `name'
+ must uniquely identify the object. For example, if the object
+ represents a file, then `name' could be the absolute path name
+ of the file.
+
+ SEE ALSO
+ SLdeallocate_load_type, SLang_load_object
+--------------------------------------------------------------
+
+SLdeallocate_load_type
+
+ SYNOPSIS
+ Free a SLang_Load_Type object
+
+ USAGE
+ void SLdeallocate_load_type (SLang_Load_Type *slt)
+
+ DESCRIPTION
+ This function frees the memory associated with a
+ `SLang_Load_Type' object that was acquired from a call to the
+ `SLallocate_load_type' function.
+
+ SEE ALSO
+ SLallocate_load_type, SLang_load_object
+--------------------------------------------------------------
+
+SLang_load_object
+
+ SYNOPSIS
+ Load an object into the interpreter
+
+ USAGE
+ int SLang_load_object (SLang_Load_Type *obj)
+
+ DESCRIPTION
+ The function `SLang_load_object' is a generic function that may
+ be used to loaded an object of type `SLang_Load_Type' into the
+ interpreter. For example, the functions `SLang_load_file' and
+ `SLang_load_string' are wrappers around this function to load a
+ file and a string, respectively.
+
+ SEE ALSO
+ SLang_load_file, SLang_load_string, SLallocate_load_type
+--------------------------------------------------------------
+
+SLclass_allocate_class
+
+ SYNOPSIS
+ Allocate a class for a new data type
+
+ USAGE
+ SLang_Class_Type *SLclass_allocate_class (char *name)
+
+ DESCRIPTION
+ The purpose of this function is to allocate and initialize space
+ that defines a new data type or class called `name'. If
+ successful, a pointer to the class is returned, or upon failure the
+ function returns `NULL'.
+
+ This function does not automatically create the new data type.
+ Callback functions must first be associated with the data type via
+ functions such as `SLclass_set_push_function', and the data
+ type must be registered with the interpreter via
+ `SLclass_register_class'. See the S-Lang library programmer's
+ guide for more information.
+
+ SEE ALSO
+ SLclass_register_class, SLclass_set_push_function
+--------------------------------------------------------------
+
+SLclass_register_class
+
+ SYNOPSIS
+ Register a new data type with the interpreter
+
+ USAGE
+ int SLclass_register_class (cl, type, sizeof_type, class_type)
+
+ SLang_Class_Type *cl
+ unsigned char type
+ unsigned int sizeof_type
+ unsigned char class_type
+
+
+ DESCRIPTION
+ The `SLclass_register_class' function is used to register a new
+ class or data type with the interpreter. If successful, the
+ function returns `0', or upon failure, it returns `-1'.
+
+ The first parameter, `cl', must have been previously obtained
+ via the `SLclass_allocate_class' function.
+
+ The second parameter, `type' specifies the data type of the new
+ class. It must be an unsigned character with value greater that
+ `127'. The values in the range `0-127' are reserved for
+ internal use by the library.
+
+ The size that the data type represents in bytes is specified by the
+ third parameter, `sizeof_type'. This value should not be
+ confused with the sizeof the structure that represents the data
+ type, unless the data type is of class `SLANG_CLASS_TYPE_VECTOR'
+ or `SLANG_CLASS_TYPE_SCALAR'. For pointer objects, the value
+ of this parameter is just `sizeof(void *)'.
+
+ The final parameter specifies the class type of the data type. It must
+ be one of the values:
+
+ SLANG_CLASS_TYPE_SCALAR
+ SLANG_CLASS_TYPE_VECTOR
+ SLANG_CLASS_TYPE_PTR
+ SLANG_CLASS_TYPE_MMT
+
+ The `SLANG_CLASS_TYPE_SCALAR' indicates that the new data type
+ is a scalar. Examples of scalars in `SLANG_INT_TYPE' and
+ `SLANG_DOUBLE_TYPE'.
+
+ Setting `class_type' to SLANG_CLASS_TYPE_VECTOR implies that the
+ new data type is a vector, or a 1-d array of scalar types. An
+ example of a data type of this class is the
+ `SLANG_COMPLEX_TYPE', which represents complex numbers.
+
+ `SLANG_CLASS_TYPE_PTR' specifies the data type is of a pointer
+ type. Examples of data types of this class include
+ `SLANG_STRING_TYPE' and `SLANG_ARRAY_TYPE'. Such types must
+ provide for their own memory management.
+
+ Data types of class `SLANG_CLASS_TYPE_MMT' are pointer types
+ except that the memory management, i.e., creation and destruction of
+ the type, is handled by the interpreter. Such a type is called a
+ _memory managed type_. An example of this data type is the
+ `SLANG_FILEPTR_TYPE'.
+
+ NOTES
+ See the \slang-c-programmers-guide for more information.
+
+ SEE ALSO
+ SLclass_allocate_class
+--------------------------------------------------------------
+
+SLclass_set_string_function
+
+ SYNOPSIS
+ Set a data type's string representation callback
+
+ USAGE
+ int SLclass_set_string_function (cl, sfun)
+
+ SLang_Class_Type *cl
+ char *(*sfun) (unsigned char, VOID_STAR);
+
+
+ DESCRIPTION
+ The `SLclass_set_string_function' routine is used to define a
+ callback function, `sfun', that will be used when a string
+ representation of an object of the data type represented by `cl'
+ is needed. `cl' must have already been obtained via a call to
+ `SLclass_allocate_class'. When called, `sfun' will be
+ passed two arguments: a unsigned char which represents the data
+ type, and the address of the object for which a string represetation
+ is required. The callback function must return a _malloced_
+ string.
+
+ Upon success, `SLclass_set_string_function' returns zero, or
+ upon error it returns -1.
+
+ EXAMPLE
+ A callback function that handles both `SLANG_STRING_TYPE' and
+ `SLANG_INT_TYPE' variables looks like:
+
+ char *string_and_int_callback (unsigned char type, VOID_STAR addr)
+ {
+ char buf[64];
+
+ switch (type)
+ {
+ case SLANG_STRING_TYPE:
+ return SLmake_string (*(char **)addr);
+
+ case SLANG_INTEGER_TYPE:
+ sprintf (buf, "%d", *(int *)addr);
+ return SLmake_string (buf);
+ }
+ return NULL;
+ }
+
+
+ NOTES
+ The default string callback simply returns the name of the data type.
+
+ SEE ALSO
+ SLclass_allocate_class, SLclass_register_class
+--------------------------------------------------------------
+
+SLclass_set_destroy_function
+
+ SYNOPSIS
+ Set the destroy method callback for a data type
+
+ USAGE
+ int SLclass_set_destroy_function (cl, destroy_fun)
+
+ SLang_Class_Type *cl
+ void (*destroy_fun) (unsigned char, VOID_STAR);
+
+
+ DESCRIPTION
+ `SLclass_set_destroy_function' is used to set the destroy
+ callback for a data type. The data type's class `cl' must have
+ been previously obtained via a call to `SLclass_allocate_class'.
+ When called, `destroy_fun' will be passed two arguments: a
+ unsigned char which represents the data type, and the address of the
+ object to be destroyed.
+
+ `SLclass_set_destroy_function' returns zero upon success, and
+ -1 upon failure.
+
+ EXAMPLE
+ The destroy method for `SLANG_STRING_TYPE' looks like:
+
+ static void string_destroy (unsigned char type, VOID_STAR ptr)
+ {
+ char *s = *(char **) ptr;
+ if (s != NULL) SLang_free_slstring (*(char **) s);
+ }
+
+
+ NOTES
+ Data types of class SLANG_CLASS_TYPE_SCALAR do not require a destroy
+ callback. However, other classes do.
+
+ SEE ALSO
+ SLclass_allocate_class, SLclass_register_class
+--------------------------------------------------------------
+
+SLclass_set_push_function
+
+ SYNOPSIS
+ Set the push callback for a new data type
+
+ USAGE
+ int SLclass_set_push_function (cl, push_fun)
+
+ SLang_Class_Type *cl
+ int (*push_fun) (unsigned char, VOID_STAR);
+
+
+ DESCRIPTION
+ `SLclass_set_push_function' is used to set the push callback
+ for a new data type specified by `cl', which must have been
+ previously obtained via `SLclass_allocate_class'.
+
+ The parameter `push_fun' is a pointer to the push callback. It
+ is required to take two arguments: an unsigned character
+ representing the data type, and the address of the object to be
+ pushed. It must return zero upon success, or -1 upon failure.
+
+ `SLclass_set_push_function' returns zero upon success, or -1
+ upon failure.
+
+ EXAMPLE
+ The push callback for `SLANG_COMPLEX_TYPE' looks like:
+
+ static int complex_push (unsigned char type, VOID_STAR ptr)
+ {
+ double *z = *(double **) ptr;
+ return SLang_push_complex (z[0], z[1]);
+ }
+
+
+ SEE ALSO
+ SLclass_allocate_class, SLclass_register_class
+--------------------------------------------------------------
+
+SLclass_set_pop_function
+
+ SYNOPSIS
+ Set the pop callback for a new data type
+
+ USAGE
+ int SLclass_set_pop_function (cl, pop_fun)
+
+ SLang_Class_Type *cl
+ int (*pop_fun) (unsigned char, VOID_STAR);
+
+
+ DESCRIPTION
+ `SLclass_set_pop_function' is used to set the callback for
+ popping an object from the stack for a new data type specified by
+ `cl', which must have been previously obtained via
+ `SLclass_allocate_class'.
+
+ The parameter `pop_fun' is a pointer to the pop callback
+ function, which is required to take two arguments: an unsigned
+ character representing the data type, and the address of the object
+ to be popped. It must return zero upon success, or -1 upon
+ failure.
+
+ `SLclass_set_pop_function' returns zero upon success, or -1
+ upon failure.
+
+ EXAMPLE
+ The pop callback for `SLANG_COMPLEX_TYPE' looks like:
+
+ static int complex_push (unsigned char type, VOID_STAR ptr)
+ {
+ double *z = *(double **) ptr;
+ return SLang_pop_complex (&z[0], &z[1]);
+ }
+
+
+ SEE ALSO
+ SLclass_allocate_class, SLclass_register_class
+--------------------------------------------------------------
+
+SLclass_get_datatype_name
+
+ SYNOPSIS
+ Get the name of a data type
+
+ USAGE
+ char *SLclass_get_datatype_name (unsigned char type)
+
+ DESCRIPTION
+ The `SLclass_get_datatype_name' function returns the name of the
+ data type specified by `type'. For example, if `type' is
+ `SLANG_INT_TYPE', the string `"Integer_Type"' will be
+ returned.
+
+ This function returns a pointer that should not be modified or freed.
+
+ SEE ALSO
+ SLclass_allocate_class, SLclass_register_class
+--------------------------------------------------------------
+
+SLang_free_mmt
+
+ SYNOPSIS
+ Free a memory managed type
+
+ USAGE
+ void SLang_free_mmt (SLang_MMT_Type *mmt)
+
+ DESCRIPTION
+ The `SLang_MMT_Type' function is used to free a memory managed
+ data type.
+
+ SEE ALSO
+ SLang_object_from_mmt, SLang_create_mmt
+--------------------------------------------------------------
+
+SLang_object_from_mmt
+
+ SYNOPSIS
+ Get a pointer to the value of a memory managed type
+
+ USAGE
+ VOID_STAR SLang_object_from_mmt (SLang_MMT_Type *mmt)
+
+ DESCRIPTION
+ The `SLang_object_from_mmt' function returns a pointer to the
+ actual object whose memory is being managed by the interpreter.
+
+ SEE ALSO
+ SLang_free_mmt, SLang_create_mmt
+--------------------------------------------------------------
+
+SLang_create_mmt
+
+ SYNOPSIS
+ Create a memory managed data type
+
+ USAGE
+ SLang_MMT_Type *SLang_create_mmt (unsigned char t, VOID_STAR ptr)
+
+ DESCRIPTION
+ The `SLang_create_mmt' function returns a pointer to a new
+ memory managed object. This object contains information necessary
+ to manage the memory associated with the pointer `ptr' which
+ represents the application defined data type of type `t'.
+
+ SEE ALSO
+ SLang_object_from_mmt, SLang_push_mmt, SLang_free_mmt
+--------------------------------------------------------------
+
+SLang_push_mmt
+
+ SYNOPSIS
+ Push a memory managed type
+
+ USAGE
+ int SLang_push_mmt (SLang_MMT_Type *mmt)
+
+ DESCRIPTION
+ This function is used to push a memory managed type onto the
+ interpreter stack. It returns zero upon success, or `-1' upon
+ failure.
+
+ SEE ALSO
+ SLang_create_mmt, SLang_pop_mmt
+--------------------------------------------------------------
+
+SLang_pop_mmt
+
+ SYNOPSIS
+ Pop a memory managed data type
+
+ USAGE
+ SLang_MMT_Type *SLang_pop_mmt (unsigned char t)
+
+ DESCRIPTION
+ The `SLang_pop_mmt' function may be used to pop a memory managed
+ type of type `t' from the stack. It returns a pointer to the
+ memory managed object upon success, or `NULL' upon failure. The
+ function `SLang_object_from_mmt' should be used to access the
+ actual pointer to the data type.
+
+ SEE ALSO
+ SLang_object_from_mmt, SLang_push_mmt
+--------------------------------------------------------------
+
+SLang_inc_mmt
+
+ SYNOPSIS
+ Increment a memory managed type reference count
+
+ USAGE
+ void SLang_inc_mmt (SLang_MMT_Type *mmt);
+
+ DESCRIPTION
+ The `SLang_inc_mmt' function may be used to increment the
+ reference count associated with the memory managed data type given
+ by `mmt'.
+
+ SEE ALSO
+ SLang_free_mmt, SLang_create_mmt, SLang_pop_mmt, SLang_pop_mmt
+--------------------------------------------------------------
+
+SLang_vmessage
+
+ SYNOPSIS
+ Display a message to the message device
+
+ USAGE
+ void SLang_vmessage (char *fmt, ...)
+
+ DESCRIPTION
+ This function prints a `printf' style formatted variable
+ argument list to the message device. The default message device is
+ `stdout'.
+
+ SEE ALSO
+ SLang_verror
+--------------------------------------------------------------
+
+SLang_exit_error
+
+ SYNOPSIS
+ Exit the program and display an error message
+
+ USAGE
+ void SLang_exit_error (char *fmt, ...)
+
+ DESCRIPTION
+ The `SLang_exit_error' function terminates the program and
+ displays an error message using a `printf' type variable
+ argument list. The default behavior to this function is to write
+ the message to `stderr' and exit with the `exit' system
+ call.
+
+ If the function pointer `SLang_Exit_Error_Hook' is
+ non-NULL, the function to which it points will be called. This
+ permits an application to perform whatever cleanup is necessary.
+ This hook has the prototype:
+
+ void (*SLang_Exit_Error_Hook)(char *, va_list);
+
+
+ SEE ALSO
+ SLang_verror, exit
+--------------------------------------------------------------
+
+SLang_init_slang
+
+ SYNOPSIS
+ Initialize the interpreter
+
+ USAGE
+ int SLang_init_slang (void)
+
+ DESCRIPTION
+ The `SLang_init_slang' function must be called by all
+ applications that use the S-Lang interpreter. It initializes the
+ interpreter, defines the built-in data types, and adds a set of core
+ intrinsic functions.
+
+ The function returns `0' upon success, or `-1' upon failure.
+
+ SEE ALSO
+ SLang_init_slfile, SLang_init_slmath, SLang_init_slunix
+--------------------------------------------------------------
+
+SLang_init_slfile
+
+ SYNOPSIS
+ Initialize the interpreter file I/O intrinsics
+
+ USAGE
+ int SLang_init_slfile (void)
+
+ DESCRIPTION
+ This function initializes the interpreters file I/O intrinsic
+ functions. This function adds intrinsic functions such as
+ `fopen', `fclose', and `fputs' to the interpreter.
+ It returns `0' if successful, or `-1' upon error.
+
+ NOTES
+ Before this function can be called, it is first necessary to call
+ `SLang_init_slang'. It also adds
+ the preprocessor symbol `__SLFILE__' to the interpreter.
+
+ SEE ALSO
+ SLang_init_slang, SLang_init_slunix, SLang_init_slmath
+--------------------------------------------------------------
+
+SLang_init_slmath
+
+ SYNOPSIS
+ Initialize the interpreter math intrinsics
+
+ USAGE
+ int SLang_init_slmath (void)
+
+ DESCRIPTION
+ The `SLang_init_slmath' function initializes the interpreter's
+ mathematical intrinsic functions and makes them available to the
+ language. The intrinsic functions include `sin', `cos',
+ `tan', etc... It returns `0' if successful, or `-1'
+ upon failure.
+
+ NOTES
+ This function must be called after `SLang_init_slang'. It adds
+ the preprocessor symbol `__SLMATH__' to the interpreter.
+
+ SEE ALSO
+ SLang_init_slang, SLang_init_slfile, SLang_init_slunix
+--------------------------------------------------------------
+
+SLang_init_slunix
+
+ SYNOPSIS
+ Make available some unix system calls to the interpreter
+
+ USAGE
+ int SLang_init_slunix (void)
+
+ DESCRIPTION
+ The `SLang_init_slunix' function initializes the interpreter's
+ unix system call intrinsic functions and makes them available to the
+ language. Examples of functions made available by
+ `SLang_init_slunix' include `chmod', `chown', and
+ `stat_file'. It returns `0' if successful, or `-1'
+ upon failure.
+
+ NOTES
+ This function must be called after `SLang_init_slang'. It adds
+ the preprocessor symbol `__SLUNIX__' to the interpreter.
+
+ SEE ALSO
+ SLang_init_slang, SLang_init_slfile, SLang_init_slmath
+--------------------------------------------------------------
+
+SLadd_intrin_fun_table
+
+ SYNOPSIS
+ Add a table of intrinsic functions to the interpreter
+
+ USAGE
+ int SLadd_intrin_fun_table(SLang_Intrin_Fun_Type *tbl, char *pp_name);
+
+ DESCRIPTION
+ The `SLadd_intrin_fun_table' function adds an array, or table, of
+ `SLang_Intrin_Fun_Type' objects to the interpreter. The first
+ parameter, `tbl' specifies the table to be added. The second
+ parameter `pp_name', if non-NULL will be added to the list of
+ preprocessor symbols.
+
+ This function returns -1 upon failure or zero upon success.
+
+ NOTES
+ A table should only be loaded one time and it is considered to be an
+ error on the part of the application if it loads a table more than
+ once.
+
+ SEE ALSO
+ SLadd_intrin_var_table, SLadd_intrinsic_function, SLdefine_for_ifdef
+--------------------------------------------------------------
+
+SLadd_intrin_var_table
+
+ SYNOPSIS
+ Add a table of intrinsic variables to the interpreter
+
+ USAGE
+ int SLadd_intrin_var_table (SLang_Intrin_Var_Type *tbl, char *pp_name);
+
+ DESCRIPTION
+ The `SLadd_intrin_var_table' function adds an array, or table, of
+ `SLang_Intrin_Var_Type' objects to the interpreter. The first
+ parameter, `tbl' specifies the table to be added. The second
+ parameter `pp_name', if non-NULL will be added to the list of
+ preprocessor symbols.
+
+ This function returns -1 upon failure or zero upon success.
+
+ NOTES
+ A table should only be loaded one time and it is considered to be an
+ error on the part of the application if it loads a table more than
+ once.
+
+ SEE ALSO
+ SLadd_intrin_var_table, SLadd_intrinsic_function, SLdefine_for_ifdef
+--------------------------------------------------------------
+
+SLang_load_file
+
+ SYNOPSIS
+ Load a file into the interpreter
+
+ USAGE
+ int SLang_load_file (char *fn)
+
+ DESCRIPTION
+ The `SLang_load_file' function opens the file whose name is
+ specified by `fn' and feeds it to the interpreter, line by line,
+ for execution. If `fn' is `NULL', the function will take
+ input from `stdin'.
+
+ If no error occurs, it returns `0'; otherwise,
+ it returns `-1', and sets `SLang_Error' accordingly. For
+ example, if it fails to open the file, it will return `-1' with
+ `SLang_Error' set to `SL_OBJ_NOPEN'.
+
+ NOTES
+ If the hook `SLang_Load_File_Hook' declared as
+
+ int (*SLang_Load_File_Hook)(char *);
+
+ is non-NULL, the function point to by it will be used to load the
+ file. For example, the jed editor uses this hook to load files
+ via its own routines.
+
+ SEE ALSO
+ SLang_load_object, SLang_load_string
+--------------------------------------------------------------
+
+SLang_restart
+
+ SYNOPSIS
+ Reset the interpreter after an error
+
+ USAGE
+ void SLang_restart (int full)
+
+ DESCRIPTION
+ The `SLang_restart' function should be called by the
+ application at top level if an error occurs. If the parameter
+ `full' is non-zero, any objects on the S-Lang run time stack
+ will be removed from the stack; otherwise, the stack will be left
+ intact. Any time the stack is believed to be trashed, this routine
+ should be called with a non-zero argument (e.g., if
+ `setjmp'/`longjmp' is called).
+
+ Calling `SLang_restart' does not reset the global variable
+ `SLang_Error' to zero. It is up to the application to reset
+ that variable to zero after calling `SLang_restart'.
+
+ EXAMPLE
+
+ while (1)
+ {
+ if (SLang_Error)
+ {
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+ (void) SLang_load_file (NULL);
+ }
+
+
+ SEE ALSO
+ SLang_init_slang, SLang_load_file
+--------------------------------------------------------------
+
+SLang_byte_compile_file
+
+ SYNOPSIS
+ Byte-compile a file for faster loading
+
+ USAGE
+ int SLang_byte_compile_file(char *fn, int reserved)
+
+ DESCRIPTION
+ The `SLang_byte_compile_file' function ``byte-compiles'' the
+ file `fn' for faster loading by the interpreter. This produces
+ a new file whose filename is equivalent to the one specified by
+ `fn', except that a `'c'' is appended to the name. For
+ example, if `fn' is set to `init.sl', then the new file
+ will have the name exmp{init.slc}. The meaning of the second
+ parameter, `reserved', is reserved for future use. For now, set
+ it to `0'.
+
+ The function returns zero upon success, or `-1' upon error and
+ sets SLang_Error accordingly.
+
+ SEE ALSO
+ SLang_load_file, SLang_init_slang
+--------------------------------------------------------------
+
+SLang_autoload
+
+ SYNOPSIS
+ Autoload a function from a file
+
+ USAGE
+ int SLang_autoload(char *funct, char *filename)
+
+ DESCRIPTION
+ The `SLang_autoload' function may be used to associate a
+ `slang' function name `funct' with the file `filename'
+ such that if `funct' has not already been defined when needed,
+ it will be loaded from `filename'.
+
+ `SLang_autoload' has no effect if `funct' has already been
+ defined. Otherwise it declares `funct' as a user-defined S-Lang
+ function. It returns `0' upon success, or `-1' upon error.
+
+ SEE ALSO
+ SLang_load_file, SLang_is_defined
+--------------------------------------------------------------
+
+SLang_load_string
+
+ SYNOPSIS
+ Interpret a string
+
+ USAGE
+ int SLang_load_string(char *str)
+
+ DESCRIPTION
+ The `SLang_load_string' function feeds the string specified by
+ `str' to the interpreter for execution. It returns zero upon
+ success, or `-1' upon failure.
+
+ SEE ALSO
+ SLang_load_file, SLang_load_object
+--------------------------------------------------------------
+
+SLdo_pop
+
+ SYNOPSIS
+ Delete an object from the stack
+
+ USAGE
+ int SLdo_pop(void)
+
+ DESCRIPTION
+ This function removes an object from the top of the interpeter's
+ run-time stack and frees any memory associated with it. It returns
+ zero upon success, or `-1' upon error (most likely due to a
+ stack-underflow).
+
+ SEE ALSO
+ SLdo_pop_n, SLang_pop_integer, SLang_pop_string
+--------------------------------------------------------------
+
+SLdo_pop_n
+
+ SYNOPSIS
+ Delete n objects from the stack
+
+ USAGE
+ int SLdo_pop_n (unsigned int n)
+
+ DESCRIPTION
+ The `SLdo_pop_n' function removes the top `n' objects from
+ the interpreter's run-time stack and frees all memory associated
+ with the objects. It returns zero upon success, or `-1' upon
+ error (most likely due to a stack-underflow).
+
+ SEE ALSO
+ SLdo_pop, SLang_pop_integer, SLang_pop_string
+--------------------------------------------------------------
+
+SLang_pop_integer
+
+ SYNOPSIS
+ Pop an integer off the stack
+
+ USAGE
+ int SLang_pop_integer (int *i)
+
+ DESCRIPTION
+ The `SLang_pop_integer' function removes an integer from the
+ top of the interpreter's run-time stack and returns its value via
+ the pointer `i'. If successful, it returns zero. However, if
+ the top stack item is not of type `SLANG_INT_TYPE', or the
+ stack is empty, the function will return `-1' and set
+ `SLang_Error' accordingly.
+
+ SEE ALSO
+ SLang_push_integer, SLang_pop_double
+--------------------------------------------------------------
+
+SLpop_string
+
+ SYNOPSIS
+ Pop a string from the stack
+
+ USAGE
+ int SLpop_string (char **strptr);
+
+ DESCRIPTION
+ The `SLpop_string' function pops a string from the stack and
+ returns it as a malloced pointer. It is up to the calling routine
+ to free this string via a call to `free' or `SLfree'. If
+ successful, `SLpop_string' returns zero. However, if the top
+ stack item is not of type `SLANG_STRING_TYPE', or the stack is
+ empty, the function will return `-1' and set
+ `SLang_Error' accordingly.
+
+ EXAMPLE
+
+ define print_string (void)
+ {
+ char *s;
+ if (-1 == SLpop_string (&s))
+ return;
+ fputs (s, stdout);
+ SLfree (s);
+ }
+
+
+ NOTES
+ This function should not be confused with `SLang_pop_slstring',
+ which pops a _hashed_ string from the stack.
+
+ SEE ALSO
+ SLang_pop_slstring. SLfree
+--------------------------------------------------------------
+
+SLang_pop_string
+
+ SYNOPSIS
+ Pop a string from the stack
+
+ USAGE
+ int SLang_pop_string(char **strptr, int *do_free)
+
+ DESCRIPTION
+ The `SLpop_string' function pops a string from the stack and
+ returns it as a malloced pointer via `strptr'. After the
+ function returns, the integer pointed to by the second parameter
+ will be set to a non-zero value if `*strptr' should be freed via
+ `free' or `SLfree'. If successful, `SLpop_string'
+ returns zero. However, if the top stack item is not of type
+ `SLANG_STRING_TYPE', or the stack is empty, the function will
+ return `-1' and set `SLang_Error' accordingly.
+
+ NOTES
+ This function is considered obsolete and should not be used by
+ applications. If one requires a malloced string for modification,
+ `SLpop_string' should be used. If one requires a constant
+ string that will not be modifed by the application,
+ `SLang_pop_slstring' should be used.
+
+ SEE ALSO
+ SLang_pop_slstring, SLpop_string
+--------------------------------------------------------------
+
+SLang_pop_slstring
+
+ SYNOPSIS
+ Pop a hashed string from the stack
+
+ USAGE
+ int SLang_pop_slstring (char **s_ptr)
+
+ DESCRIPTION
+ The `SLang_pop_slstring' function pops a hashed string from the
+ S-Lang run-time stack and returns it via `s_ptr'. It returns
+ zero if successful, or -1 upon failure. The resulting string
+ should be freed via a call to `SLang_free_slstring' after use.
+
+ EXAMPLE
+
+ void print_string (void)
+ {
+ char *s;
+ if (-1 == SLang_pop_slstring (&s))
+ return;
+ fprintf (stdout, "%s\n", s);
+ SLang_free_slstring (s);
+ }
+
+
+ NOTES
+ `SLang_free_slstring' is the preferred function for popping
+ strings. This is a result of the fact that the interpreter uses
+ hashed strings as the native representation for string data.
+
+ One must _never_ free a hashed string using `free' or
+ `SLfree'. In addition, one must never make any attempt to
+ modify a hashed string and doing so will result in memory
+ corruption.
+
+ SEE ALSO
+ SLang_free_slstring, SLpop_string
+--------------------------------------------------------------
+
+SLang_pop_double
+
+ SYNOPSIS
+ Pop a double from the stack
+
+ USAGE
+ int SLang_pop_double (double *dptr, int *iptr, int *conv)
+
+ DESCRIPTION
+ The `SLang_pop_double' function pops a double precision number
+ from the stack and returns it via `dptr'. If the number was
+ derived from an integer, `*conv' will be set to `1' upon
+ return, otherwise, `*conv' will be set to `0'. This
+ function returns 0 upon success, otherwise it returns -1 and sets
+ `SLang_Error' accordingly.
+
+ NOTES
+ If one does not care whether or not `*dptr' was derived from
+ an integer, `iptr' and `conv' may be passed as `NULL'
+ pointers.
+
+ SEE ALSO
+ SLang_pop_integer, SLang_push_double
+--------------------------------------------------------------
+
+SLang_pop_complex
+
+ SYNOPSIS
+ Pop a complex number from the stack
+
+ USAGE
+ int SLang_pop_complex (double *re, double *im)
+
+ DESCRIPTION
+ `SLang_pop_complex' pops a complex number from the stack and
+ returns it via the parameters `re' and `im' as the real and
+ imaginary parts of the complex number, respectively. This function
+ automatically converts objects of type `SLANG_DOUBLE_TYPE' and
+ `SLANG_INT_TYPE' to `SLANG_COMPLEX_TYPE', if necessary.
+ It returns zero upon success, or -1 upon error setting
+ `SLang_Error' accordingly.
+
+ SEE ALSO
+ SLang_pop_integer, SLang_pop_double, SLang_push_complex
+--------------------------------------------------------------
+
+SLang_push_complex
+
+ SYNOPSIS
+ Push a complex number onto the stack
+
+ USAGE
+ int SLang_push_complex (double re, double im)
+
+ DESCRIPTION
+ `SLang_push_complex' may be used to push the complex number
+ whose real and imaginary parts are given by `re' and `im',
+ respectively. It returns zero upon success, or -1 upon error
+ setting `SLang_Error' accordingly.
+
+ SEE ALSO
+ SLang_pop_complex, SLang_push_double
+--------------------------------------------------------------
+
+SLang_push_double
+
+ SYNOPSIS
+ Push a double onto the stack
+
+ USAGE
+ int SLang_push_double(double d)
+
+ DESCRIPTION
+ `SLang_push_double' may be used to push the double precision
+ floating point number `d' onto the interpreter's run-time
+ stack. It returns zero upon success, or -1 upon error setting
+ `SLang_Error' accordingly.
+
+ SEE ALSO
+ SLang_pop_double, SLang_push_integer
+--------------------------------------------------------------
+
+SLang_push_string
+
+ SYNOPSIS
+ Push a string onto the stack
+
+ USAGE
+ int SLang_push_string (char *s)
+
+ DESCRIPTION
+ `SLang_push_string' pushes a copy of the string specified by
+ `s' onto the interpreter's run-time stack. It returns zero
+ upon success, or -1 upon error setting `SLang_Error'
+ accordingly.
+
+ NOTES
+ If `s' is `NULL', this function pushes `NULL'
+ (`SLANG_NULL_TYPE') onto the stack.
+
+ SEE ALSO
+ SLang_push_malloced_string
+--------------------------------------------------------------
+
+SLang_push_integer
+
+ SYNOPSIS
+ Push an integer onto the stack
+
+ USAGE
+ int SLang_push_integer (int i)
+
+ DESCRIPTION
+ `SLang_push_integer' the integer `i' onto the interpreter's
+ run-time stack. It returns zero upon success, or -1 upon error
+ setting `SLang_Error' accordingly.
+
+ SEE ALSO
+ SLang_pop_integer, SLang_push_double, SLang_push_string
+--------------------------------------------------------------
+
+SLang_push_malloced_string
+
+ SYNOPSIS
+ Push a malloced string onto the stack
+
+ USAGE
+ int SLang_push_malloced_string (char *s);
+
+ DESCRIPTION
+ `SLang_push_malloced_string' may be used to push a malloced
+ string onto the interpreter's run-time stack. It returns zero upon
+ success, or -1 upon error setting `SLang_Error' accordingly.
+
+ EXAMPLE
+ The following example illustrates that it is up to the calling
+ routine to free the string if `SLang_push_malloced_string' fails:
+
+ int push_hello (void)
+ {
+ char *s = malloc (6);
+ if (s == NULL) return -1;
+ strcpy (s, "hello");
+ if (-1 == SLang_push_malloced_string (s))
+ {
+ free (s);
+ return -1;
+ }
+ return 0;
+ }
+
+
+ EXAMPLE
+ The function `SLang_create_slstring' returns a hashed string.
+ Such a string may not be malloced and should not be passed to
+ `SLang_push_malloced_string'.
+
+ NOTES
+ If `s' is `NULL', this function pushes `NULL'
+ (`SLANG_NULL_TYPE') onto the stack.
+
+ SEE ALSO
+ SLang_push_string, SLmake_string
+--------------------------------------------------------------
+
+SLang_is_defined
+
+ SYNOPSIS
+ Check to see if the interpreter defines an object
+
+ USAGE
+ int SLang_is_defined (char *nm)
+
+ DESCRIPTION
+ The `SLang_is_defined' function may be used to determine
+ whether or not a variable or function whose name is given by
+ `em' has been defined. It returns zero if no such object has
+ been defined. Othewise it returns a non-zero value whose meaning
+ is given by the following table:
+
+ 1 intrinsic function (SLANG_INTRINSIC)
+ 2 user-defined slang function (SLANG_FUNCTION)
+ -1 intrinsic variable (SLANG_IVARIABLE)
+ -2 user-defined global variable (SLANG_GVARIABLE)
+
+
+ SEE ALSO
+ SLadd_intrinsic_function, SLang_run_hooks, SLang_execute_function
+--------------------------------------------------------------
+
+SLang_run_hooks
+
+ SYNOPSIS
+ Run a user-defined hook with arguments
+
+ USAGE
+ int SLang_run_hooks (char *fname, unsigned int n, ...)
+
+ DESCRIPTION
+ The `SLang_run_hooks' function may be used to execute a
+ user-defined function named `fname'. Before execution of the
+ function, the `n' string arguments specified by the variable
+ parameter list are pushed onto the stack. If the function
+ `fname' does not exist, `SLang_run_hooks' returns zero;
+ otherwise, it returns `1' upon successful execution of the
+ function, or -1 if an error occurred.
+
+ EXAMPLE
+ The jed editor uses `SLang_run_hooks' to setup the mode of a
+ buffer based on the filename extension of the file associated with
+ the buffer:
+
+ char *ext = get_filename_extension (filename);
+ if (ext == NULL) return -1;
+ if (-1 == SLang_run_hooks ("mode_hook", 1, ext))
+ return -1;
+ return 0;
+
+
+ SEE ALSO
+ SLang_is_defined, SLang_execute_function
+--------------------------------------------------------------
+
+SLang_execute_function
+
+ SYNOPSIS
+ Execute a user or intrinsic function
+
+ USAGE
+ int SLang_execute_function (char *fname)
+
+ DESCRIPTION
+ This function may be used to execute either a user-defined function
+ or an intrinisic function. The name of the function is specified
+ by `fname'. It returns zero if `fname' is not defined, or
+ `1' if the function was successfully executed, or -1 upon
+ error.
+
+ NOTES
+ The function `SLexecute_function' may be a better alternative
+ for some uses.
+
+ SEE ALSO
+ SLang_run_hooks, SLexecute_function, SLang_is_defined
+--------------------------------------------------------------
+
+SLang_verror
+
+ SYNOPSIS
+ Signal an error with a message
+
+ USAGE
+ void SLang_verror (int code, char *fmt, ...);
+
+ DESCRIPTION
+ The `SLang_verror' function sets `SLang_Error' to
+ `code' if `SLang_Error' is 0. It also displays the error
+ message implied by the `printf' variable argument list using
+ `fmt' as the format.
+
+ EXAMPLE
+
+ FILE *open_file (char *file)
+ {
+ char *file = "my_file.dat";
+ if (NULL == (fp = fopen (file, "w")))
+ SLang_verror (SL_INTRINSIC_ERROR, "Unable to open %s", file);
+ return fp;
+ }
+
+
+ SEE ALSO
+ SLang_vmessage, SLang_exit_error
+--------------------------------------------------------------
+
+SLang_doerror
+
+ SYNOPSIS
+ Signal an error
+
+ USAGE
+ void SLang_doerror (char *err_str)
+
+ DESCRIPTION
+ The `SLang_doerror' function displays the string `err_str'
+ to the error device and signals a S-Lang error.
+
+ NOTES
+ `SLang_doerror' is considered to obsolete. Applications should
+ use the `SLang_verror' function instead.
+
+ SEE ALSO
+ SLang_verror, SLang_exit_error
+--------------------------------------------------------------
+
+SLang_get_function
+
+ SYNOPSIS
+ Get a pointer to a slang function
+
+ USAGE
+ SLang_Name_Type *SLang_get_function (char *fname)
+
+ DESCRIPTION
+ This function returns a pointer to the internal S-Lang table entry
+ of a function whose name is given by `fname'. It returns
+ `NULL' upon failure. The value returned by this function can be
+ used `SLexecute_function' to call the function directly
+ from C.
+
+ SEE ALSO
+ SLexecute_function
+--------------------------------------------------------------
+
+SLexecute_function
+
+ SYNOPSIS
+ Execute a slang or intrinsic function
+
+ USAGE
+ int SLexecute_function (SLang_Name_Type *nt)
+
+ DESCRIPTION
+ The `SLexecute_function' allows an application to call the
+ S-Lang function specified by the `SLang_Name_Type' pointer
+ `nt'. This parameter must be non `NULL' and must have been
+ previously obtained by a call to `SLang_get_function'.
+
+ EXAMPLE
+ Consider the S-Lang function:
+
+ define my_fun (x)
+ {
+ return x^2 - 2;
+ }
+
+ Suppose that it is desired to call this function many times with
+ different values of x. There are at least two ways to do this.
+ The easiest way is to use `SLang_execute_function' by passing
+ the string `"my_fun"'. A better way that is much faster is to
+ use `SLexecute_function':
+
+ int sum_a_function (char *fname, double *result)
+ {
+ double sum, x, y;
+ SLang_Name_Type *nt;
+
+ if (NULL == (nt = SLang_get_function (fname)))
+ return -1;
+
+ sum = 0;
+ for (x = 0; x < 10.0; x += 0.1)
+ {
+ SLang_start_arg_list ();
+ if (-1 == SLang_push_double (x))
+ return -1;
+ SLang_end_arg_list ();
+ if (-1 == SLexecute_function (nt))
+ return -1;
+ if (-1 == SLang_pop_double (&y, NULL, NULL))
+ return -1;
+
+ sum += y;
+ }
+ return sum;
+ }
+
+ Although not necessary in this case, `SLang_start_arg_list' and
+ `SLang_end_arg_list' were used to provide the function with
+ information about the number of parameters passed to it.
+
+ SEE ALSO
+ SLang_get_function, SLang_start_arg_list, SLang_end_arg_list
+--------------------------------------------------------------
+
+SLang_peek_at_stack
+
+ SYNOPSIS
+ Find the type of object on the top of the stack
+
+ USAGE
+ int SLang_peek_at_stack (void)
+
+ DESCRIPTION
+ The `SLang_peek_at_stack' function is useful for determining the
+ data type of the object at the top of the stack. It returns the
+ data type, or -1 upon a stack-underflow error. It does not remove
+ anything from the stack.
+
+ SEE ALSO
+ SLang_pop_string, SLang_pop_integer
+--------------------------------------------------------------
+
+SLmake_string
+
+ SYNOPSIS
+ Duplicate a string
+
+ USAGE
+ char *SLmake_string (char *s)
+
+ DESCRIPTION
+ The `SLmake_string' function creates a new copy of the string
+ `s', via `malloc', and returns it. Upon failure it returns
+ `NULL'. Since the resulting string is malloced, it should be
+ freed when nolonger needed via a call to either `free' or
+ `SLfree'.
+
+ NOTES
+ `SLmake_string' should not be confused with the function
+ `SLang_create_slstring', which performs a similar function.
+
+ SEE ALSO
+ SLmake_nstring, SLfree, SLmalloc, SLang_create_slstring
+--------------------------------------------------------------
+
+SLmake_nstring
+
+ SYNOPSIS
+ Duplicate a substring
+
+ USAGE
+ char *SLmake_nstring (char *s, unsigned int n)
+
+ DESCRIPTION
+ This function is like `SLmake_nstring' except that it creates a
+ null terminated string formed from the first `n' characters of
+ `s'. Upon failure, it returns `NULL', otherwise it returns
+ the new string. When nolonger needed, the returned string should be
+ freed with either `free' or `SLfree'.
+
+ SEE ALSO
+ SLmake_nstring, SLfree, SLang_create_nslstring
+--------------------------------------------------------------
+
+SLang_create_nslstring
+
+ SYNOPSIS
+ Created a hashed substring
+
+ USAGE
+ char *SLang_create_nslstring (char *s, unsigned int n)
+
+ DESCRIPTION
+ `SLang_create_nslstring' is like `SLang_create_slstring'
+ except that only the first `n' characters of `s' are used to
+ perform the string. Upon error, it returns `NULL', otherwise it
+ returns the hashed substring. Such a string must be freed by the
+ function `SLang_free_slstring'.
+
+ NOTES
+ Do not use `free' or `SLfree' to free the string returned by
+ `SLang_create_slstring' or `SLang_create_nslstring'. Also
+ it is important that no attempt is made to modify the hashed string
+ returned by either of these functions. If one needs to modify a
+ string, the functions `SLmake_string' or `SLmake_nstring'
+ should be used instead.
+
+ SEE ALSO
+ SLang_free_slstring, SLang_create_slstring, SLmake_nstring
+--------------------------------------------------------------
+
+SLang_create_slstring
+
+ SYNOPSIS
+ Create a hashed string
+
+ USAGE
+ char *SLang_create_slstring (char *s)
+
+ DESCRIPTION
+ The `SLang_create_slstring' creates a copy of `s' and
+ returns it as a hashed string. Upon error, the function returns
+ `NULL', otherwise it returns the hashed string. Such a string
+ must only be freed via the `SLang_free_slstring' function.
+
+ NOTES
+ Do not use `free' or `SLfree' to free the string returned by
+ `SLang_create_slstring' or `SLang_create_nslstring'. Also
+ it is important that no attempt is made to modify the hashed string
+ returned by either of these functions. If one needs to modify a
+ string, the functions `SLmake_string' or `SLmake_nstring'
+ should be used instead.
+
+ SEE ALSO
+ SLang_free_slstring, SLang_create_nslstring, SLmake_string
+--------------------------------------------------------------
+
+SLang_free_slstring
+
+ SYNOPSIS
+ Free a hashed string
+
+ USAGE
+ void SLang_free_slstring (char *s)
+
+ DESCRIPTION
+ The `SLang_free_slstring' function is used to free a hashed
+ string such as one returned by `SLang_create_slstring',
+ `SLang_create_nslstring', or `SLang_create_static_slstring'.
+ If `s' is `NULL', the routine does nothing.
+
+ SEE ALSO
+ SLang_create_slstring, SLang_create_nslstring, SLang_create_static_slstring
+--------------------------------------------------------------
+
+SLang_concat_slstrings
+
+ SYNOPSIS
+ Concatenate two strings to produce a hashed string
+
+ USAGE
+ char *SLang_concat_slstrings (char *a, char *b)
+
+ DESCRIPTION
+ The `SLang_concat_slstrings' function concatenates two strings,
+ `a' and `b', and returns the result as a hashed string.
+ Upon failure, `NULL' is returned.
+
+ NOTES
+ A hashed string can only be freed using `SLang_free_slstring'.
+ Never use either `free' or `SLfree' to free a hashed string,
+ otherwise memory corruption will result.
+
+ SEE ALSO
+ SLang_free_slstring, SLang_create_slstring
+--------------------------------------------------------------
+
+SLang_create_static_slstring
+
+ SYNOPSIS
+ Create a hashed string
+
+ USAGE
+ char *SLang_create_static_slstring (char *s_literal)
+
+ DESCRIPTION
+ The `SLang_create_static_slstring' creates a hashed string from
+ the string literal `s_literal' and returns the result. Upon
+ failure it returns `NULL'.
+
+ EXAMPLE
+
+ char *create_hello (void)
+ {
+ return SLang_create_static_slstring ("hello");
+ }
+
+
+ NOTES
+ This function should only be used with string literals.
+
+ SEE ALSO
+ SLang_create_slstring, SLang_create_nslstring
+--------------------------------------------------------------
+
+SLmalloc
+
+ SYNOPSIS
+ Allocate some memory
+
+ USAGE
+ char *SLmalloc (unsigned int nbytes)
+
+ DESCRIPTION
+ This function uses `malloc' to allocate `nbytes' of memory.
+ Upon error it returns `NULL'; otherwise it returns a pointer to
+ the allocated memory. One should use `SLfree' to free the
+ memory after used.
+
+ SEE ALSO
+ SLfree, SLrealloc, SLcalloc
+--------------------------------------------------------------
+
+SLcalloc
+
+ SYNOPSIS
+ Allocate some memory
+
+ USAGE
+ char *SLcalloc (unsigned int num_elem, unsigned int elem_size)
+
+ DESCRIPTION
+ This function uses `calloc' to allocate memory for
+ `num_elem' objects with each of size `elem_size' and returns
+ the result. In addition, the newly allocated memory is zeroed.
+ Upon error it returns `NULL'; otherwise it returns a pointer to
+ the allocated memory. One should use `SLfree' to free the
+ memory after used.
+
+ SEE ALSO
+ SLmalloc, SLrealloc, SLfree
+--------------------------------------------------------------
+
+SLfree
+
+ SYNOPSIS
+ Free some allocated memory
+
+ USAGE
+ void SLfree (char *ptr)
+
+ DESCRIPTION
+ The `SLfree' function uses `free' to deallocate the memory
+ specified by `ptr', which may be `NULL' in which case the
+ function does nothing.
+
+ NOTES
+ Never use this function to free a hashed string returned by one of
+ the family of `slstring' functions, e.g.,
+ `SLang_pop_slstring'.
+
+ SEE ALSO
+ SLmalloc, SLcalloc, SLrealloc, SLmake_string
+--------------------------------------------------------------
+
+SLrealloc
+
+ SYNOPSIS
+ Resize a dynamic memory block
+
+ USAGE
+ char *SLrealloc (char *ptr, unsigned int new_size)
+
+ DESCRIPTION
+ The `SLrealloc' uses the `realloc' function to resize the
+ memory block specified by `ptr' to the new size `new_size'.
+ If `ptr' is `NULL', the function call is equivalent to
+ `SLmalloc(new_size)'. Similarly, if `new_size' is zero,
+ the function call is equivalent to `SLfree(ptr)'.
+
+ If the function fails, or if `new_size' is zero, `NULL' is
+ returned. Otherwise a pointer is returned to the (possibly moved)
+ new block of memory.
+
+ SEE ALSO
+ SLfree, SLmalloc, SLcalloc
+--------------------------------------------------------------
+
+SLcurrent_time_string
+
+ SYNOPSIS
+ Get the current time as a string
+
+ USAGE
+ char *SLcurrent_time_string (void)
+
+ DESCRIPTION
+ The `SLcurrent_time_string' function uses the C library function
+ `ctime' to obtain a string representation of the
+ current date and time in the form
+
+ "Wed Dec 10 12:50:28 1997"
+
+ However, unlike the `ctime' function, a newline character is not
+ present in the string.
+
+ The returned value points to a statically allocated memory block
+ which may get overwritten on subsequent function calls.
+
+ SEE ALSO
+ SLmake_string
+--------------------------------------------------------------
+
+SLatoi
+
+ SYNOPSIS
+ Convert a text string to an integer
+
+ USAGE
+ int SLatoi(unsigned char *str
+
+ DESCRIPTION
+ `SLatoi' parses the string `str' to interpret it as an
+ integer value. Unlike `atoi', `SLatoi' can also parse
+ strings containing integers expressed in
+ hexidecimal (e.g., `"0x7F"') and octal (e.g., `"012"'.)
+ notation.
+
+ SEE ALSO
+ SLang_guess_type
+--------------------------------------------------------------
+
+SLang_pop_fileptr
+
+ SYNOPSIS
+ Pop a file pointer
+
+ USAGE
+ int SLang_pop_fileptr (SLang_MMT_Type **mmt, FILE **fp)
+
+ DESCRIPTION
+ `SLang_pop_fileptr' pops a file pointer from the S-Lang
+ run-time stack. It returns zero upon success, or -1 upon failure.
+
+ A S-Lang file pointer (SLANG_FILEPTR_TYPE) is actually a memory
+ managed object. For this reason, `SLang_pop_fileptr' also
+ returns the memory managed object via the argument list. It is up
+ to the calling routine to call `SLang_free_mmt' to free the
+ object.
+
+ EXAMPLE
+ The following example illustrates an application defined intrinsic
+ function that writes a user defined double precision number to a
+ file. Note the use of `SLang_free_mmt':
+
+ int write_double (void)
+ {
+ double t;
+ SLang_MMT_Type *mmt;
+ FILE *fp;
+ int status;
+
+ if (-1 == SLang_pop_double (&d, NULL, NULL))
+ return -1;
+ if (-1 == SLang_pop_fileptr (&mmt, &fp))
+ return -1;
+
+ status = fwrite (&d, sizeof (double), 1, fp);
+ SLang_free_mmt (mmt);
+ return status;
+ }
+
+ This function can be used by a S-Lang function as follows:
+
+ define write_some_values ()
+ {
+ variable fp, d;
+
+ fp = fopen ("myfile.dat", "wb");
+ if (fp == NULL)
+ error ("file failed to open");
+ for (d = 0; d < 10.0; d += 0.1)
+ {
+ if (-1 == write_double (fp, d))
+ error ("write failed");
+ }
+ if (-1 == fclose (fp))
+ error ("fclose failed");
+ }
+
+
+ SEE ALSO
+ SLang_free_mmt, SLang_pop_double
+--------------------------------------------------------------
+
+SLadd_intrinsic_function
+
+ SYNOPSIS
+ Add a new intrinsic function to the interpreter
+
+ USAGE
+ int SLadd_intrinsic_function (name, f, type, nargs, ...)
+
+ char *name
+ FVOID_STAR f
+ unsigned char type
+ unsigned int nargs
+
+
+ DESCRIPTION
+ The `SLadd_intrinsic_function' function may be used to add a new
+ intrinsic function. The S-Lang name of the function is specified by
+ `name' and the actual function pointer is given by `f', cast
+ to `FVOID_STAR'. The third parameter, `type' specifies the
+ return type of the function and must be one of the following values:
+
+ SLANG_VOID_TYPE (returns nothing)
+ SLANG_INT_TYPE (returns int)
+ SLANG_DOUBLE_TYPE (returns double)
+ SLANG_STRING_TYPE (returns char *)
+
+ The `nargs' parameter specifies the number of parameters to pass
+ to the function. The variable argument list following `nargs'
+ must consists of `nargs' integers which specify the data type of
+ each argument.
+
+ The function returns zero upon success or -1 upon failure.
+
+ EXAMPLE
+ The jed editor uses this function to change the `system'
+ intrinsic function to the following:
+
+ static int jed_system (char *cmd)
+ {
+ if (Jed_Secure_Mode)
+ {
+ msg_error ("Access denied.");
+ return -1;
+ }
+ return SLsystem (cmd);
+ }
+
+ After initializing the interpreter with `SLang_init_slang',
+ jed calls `SLadd_intrinsic_function' to substitute the above
+ definition for the default S-Lang definition:
+
+ if (-1 == SLadd_intrinsic_function ("system", (FVOID_STAR)jed_system,
+ SLANG_INT_TYPE, 1,
+ SLANG_STRING_TYPE))
+ return -1;
+
+
+ SEE ALSO
+ SLadd_intrinsic_variable, SLadd_intrinsic_array
+--------------------------------------------------------------
+
+SLadd_intrinsic_variable
+
+ SYNOPSIS
+ Add an intrinsic variable to the interpreter
+
+ USAGE
+ int SLadd_intrinsic_variable (name, addr, type, rdonly)
+
+ char *name
+ VOID_STAR type
+ unsigned char type
+ int rdonly
+
+
+ DESCRIPTION
+ The `SLadd_intrinsic_variable' function adds an intrinsic
+ variable called `name' to the interpeter. The second parameter
+ `addr' specifies the address of the variable (cast to
+ `VOID_STAR'). The third parameter, `type', specifies the
+ data type of the variable. If the fourth parameter, `rdonly',
+ is non-zero, the variable will interpreted by the interpreter as
+ read-only.
+
+ If successful, `SLadd_intrinsic_variable' returns zero,
+ otherwise it returns -1.
+
+ EXAMPLE
+ Suppose that `My_Global_Int' is a global variable (at least not
+ a local one):
+
+ int My_Global_Int;
+
+ It can be added to the interpreter via the function call
+
+ if (-1 == SLadd_intrinsic_variable ("MyGlobalInt",
+ (VOID_STAR)&My_Global_Int,
+ SLANG_INT_TYPE, 0))
+ exit (1);
+
+
+ NOTES
+ The current implementation requires all pointer type intrinsic
+ variables to be read-only. For example,
+
+ char *My_Global_String;
+
+ is of type `SLANG_STRING_TYPE', and must be declared as
+ read-only. Finally, not that
+
+ char My_Global_Char_Buf[256];
+
+ is _not_ a `SLANG_STRING_TYPE' object. This difference is
+ very important because internally the interpreter dereferences the
+ address passed to it to get to the value of the variable.
+
+ SEE ALSO
+ SLadd_intrinsic_function, SLadd_intrinsic_array
+--------------------------------------------------------------
+
+SLclass_add_unary_op
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLclass_add_unary_op (unsigned char,int (*) (int, unsigned char, VOID_STAR, unsigned int, VOID_STAR), int (*) (int, unsigned char, unsigned char *));
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLclass_add_app_unary_op
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLclass_add_app_unary_op (unsigned char, int (*) (int,unsigned char, VOID_STAR, unsigned int,VOID_STAR),int (*) (int, unsigned char, unsigned char *));
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLclass_add_binary_op
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLclass_add_binary_op (unsigned char, unsigned char,int (*)(int, unsigned char, VOID_STAR, unsigned int,unsigned char, VOID_STAR, unsigned int,VOID_STAR),int (*) (int, unsigned char, unsigned char, unsigned char *));
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLclass_add_math_op
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLclass_add_math_op (unsigned char,int (*)(int,unsigned char, VOID_STAR, unsigned int,VOID_STAR),int (*)(int, unsigned char, unsigned char *));
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLclass_add_typecast
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLclass_add_typecast (unsigned char, unsigned char int (*)_PROTO((unsigned char, VOID_STAR, unsigned int,unsigned char, VOID_STAR)),int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLang_init_tty
+
+ SYNOPSIS
+ Initialize the terminal keyboard interface
+
+ USAGE
+ int SLang_init_tty (int intr_ch, int no_flow_ctrl, int opost)
+
+ DESCRIPTION
+ `SLang_init_tty' initializes the terminal for single character
+ input. If the first parameter `intr_ch' is in the range 0-255,
+ it will be used as the interrupt character, e.g., under Unix this
+ character will generate a `SIGINT' signal. Otherwise, if it is
+ `-1', the interrupt character will be left unchanged.
+
+ If the second parameter `no_flow_ctrl' is non-zero, flow control
+ (`XON'/`XOFF') processing will be
+ enabled.
+
+ If the last parmeter `opost' is non-zero, output processing by the
+ terminal will be enabled. If one intends to use this function in
+ conjunction with the S-Lang screen management routines
+ (`SLsmg'), this paramete shold be set to zero.
+
+ `SLang_init_tty' returns zero upon success, or -1 upon error.
+
+ NOTES
+ Terminal I/O is a complex subject. The S-Lang interface presents a
+ simplification that the author has found useful in practice. For
+ example, the only special character processing that
+ `SLang_init_tty' enables is that of the `SIGINT' character,
+ and the generation of other signals via the keyboard is disabled.
+ However, generation of the job control signal `SIGTSTP' is possible
+ via the `SLtty_set_suspend_state' function.
+
+ Under Unix, the integer variable `SLang_TT_Read_FD' is used to
+ specify the input descriptor for the terminal. If
+ `SLang_TT_Read_FD' represents a terminal device as determined
+ via the `isatty' system call, then it will be used as the
+ terminal file descriptor. Otherwise, the terminal device
+ `/dev/tty' will used as the input device. The default value of
+ `SLang_TT_Read_FD' is -1 which causes `/dev/tty' to be
+ used. So, if you prefer to use `stdin' for input, then set
+ `SLang_TT_Read_FD' to `fileno(stdin)' _before_ calling
+ `SLang_init_tty'.
+
+ If the variable `SLang_TT_Baud_Rate' is zero when this function
+ is called, the function will attempt to determine the baud rate by
+ querying the terminal driver and set `SLang_TT_Baud_Rate' to
+ that value.
+
+ SEE ALSO
+ SLang_reset_tty, SLang_getkey, SLtty_set_suspend_state
+--------------------------------------------------------------
+
+SLang_reset_tty
+
+ SYNOPSIS
+ Reset the terminal
+
+ USAGE
+ void SLang_reset_tty (void)
+
+ DESCRIPTION
+ `SLang_reset_tty' resets the terminal interface back to the
+ state it was in before `SLang_init_tty' was called.
+
+ SEE ALSO
+ SLang_init_tty
+--------------------------------------------------------------
+
+SLtty_set_suspend_state
+
+ SYNOPSIS
+ Enable or disable keyboard suspension
+
+ USAGE
+ void SLtty_set_suspend_state (int s)
+
+ DESCRIPTION
+ The `SLtty_set_suspend_state' function may be used to enable or
+ disable keyboard generation of the `SIGTSTP' job control signal.
+ If `s' is non-zero, generation of this signal via the terminal
+ interface will be enabled, otherwise it will be disabled.
+
+ This function should only be called after the terminal driver has be
+ initialized via `SLang_init_tty'. The `SLang_init_tty'
+ always disables the generation of `SIGTSTP' via the keyboard.
+
+ SEE ALSO
+ SLang_init_tty
+--------------------------------------------------------------
+
+SLang_getkey
+
+ SYNOPSIS
+ Read a character from the keyboard
+
+ USAGE
+ unsigned int SLang_getkey (void);
+
+ DESCRIPTION
+ The `SLang_getkey' reads a single character from the terminal
+ and returns it. The terminal must first be initialized via a call
+ to `SLang_init_tty' before this function can be called. Upon
+ success, `SLang_getkey' returns the character read from the
+ terminal, otherwise it returns `SLANG_GETKEY_ERROR'.
+
+ SEE ALSO
+ SLang_init_tty, SLang_input_pending, SLang_ungetkey
+--------------------------------------------------------------
+
+SLang_ungetkey_string
+
+ SYNOPSIS
+ Unget a key string
+
+ USAGE
+ int SLang_ungetkey_string (unsigned char *buf, unsigned int n)
+
+ DESCRIPTION
+ The `SLang_ungetkey_string' function may be used to push the
+ `n' characters pointed to by `buf' onto the buffered input
+ stream that `SLgetkey' uses. If there is not enough room for
+ the characters, -1 is returned and none are buffered. Otherwise,
+ it returns zero.
+
+ NOTES
+ The difference between `SLang_buffer_keystring' and
+ `SLang_ungetkey_string' is that the `SLang_buffer_keystring'
+ appends the characters to the end of the getkey buffer, whereas
+ `SLang_ungetkey_string' inserts the characters at the beginning
+ of the input buffer.
+
+ SEE ALSO
+ SLang_ungetkey, SLang_getkey
+--------------------------------------------------------------
+
+SLang_buffer_keystring
+
+ SYNOPSIS
+ Append a keystring to the input buffer
+
+ USAGE
+ int SLang_buffer_keystring (unsigned char *b, unsigned int len)
+
+ DESCRIPTION
+ `SLang_buffer_keystring' places the `len' characters
+ specified by `b' at the _end_ of the buffer that
+ `SLang_getkey' uses. Upon success it returns 0; otherwise, no
+ characters are buffered and it returns -1.
+
+ NOTES
+ The difference between `SLang_buffer_keystring' and
+ `SLang_ungetkey_string' is that the `SLang_buffer_keystring'
+ appends the characters to the end of the getkey buffer, whereas
+ `SLang_ungetkey_string' inserts the characters at the beginning
+ of the input buffer.
+
+ SEE ALSO
+ SLang_getkey, SLang_ungetkey, SLang_ungetkey_string
+--------------------------------------------------------------
+
+SLang_ungetkey
+
+ SYNOPSIS
+ Push a character back onto the input buffer
+
+ USAGE
+ int SLang_ungetkey (unsigned char ch)
+
+ DESCRIPTION
+ `SLang_ungetkey' pushes the character `ch' back onto the
+ `SLgetkey' input stream. Upon success, it returns zero,
+ otherwise it returns 1.
+
+ EXAMPLE
+ This function is implemented as:
+
+ int SLang_ungetkey (unsigned char ch)
+ {
+ return SLang_ungetkey_string(&ch, 1);
+ }
+
+
+ SEE ALSO
+ SLang_getkey, SLang_ungetkey_string
+--------------------------------------------------------------
+
+SLang_flush_input
+
+ SYNOPSIS
+ Discard all keyboard input waiting to be read
+
+ USAGE
+ void SLang_flush_input (void)
+
+ DESCRIPTION
+ `SLang_flush_input' discards all input characters waiting to be
+ read by the `SLang_getkey' function.
+
+ SEE ALSO
+ SLang_getkey
+--------------------------------------------------------------
+
+SLang_input_pending
+
+ SYNOPSIS
+ Check to see if input is pending
+
+ USAGE
+ int SLang_input_pending (int tsecs)
+
+ DESCRIPTION
+ `SLang_input_pending' may be used to see if an input character
+ is available to be read without causing `SLang_getkey' to block.
+ It will wait up to `tsecs' tenths of a second if no characters
+ are immediately available for reading. If `tsecs' is less than
+ zero, then `SLang_input_pending' will wait `-tsecs'
+ milliseconds for input, otherwise `tsecs' represents `1/10'
+ of a second intervals.
+
+ NOTES
+ Not all systems support millisecond resolution.
+
+ SEE ALSO
+ SLang_getkey
+--------------------------------------------------------------
+
+SLang_set_abort_signal
+
+ SYNOPSIS
+ Set the signal to trap SIGINT
+
+ USAGE
+ void SLang_set_abort_signal (void (*f)(int));
+
+ DESCRIPTION
+ `SLang_set_abort_signal' sets the function that gets
+ triggered when the user presses the interrupt key (`SIGINT') to
+ the function `f'. If `f' is `NULL' the default handler
+ will get installed.
+
+ EXAMPLE
+ The default interrupt handler on a Unix system is:
+
+ static void default_sigint (int sig)
+ {
+ SLKeyBoard_Quit = 1;
+ if (SLang_Ignore_User_Abort == 0) SLang_Error = SL_USER_BREAK;
+ SLsignal_intr (SIGINT, default_sigint);
+ }
+
+
+ NOTES
+ For Unix programmers, the name of this function may appear
+ misleading since it is associated with `SIGINT' and not
+ `SIGABRT'. The origin of the name stems from the original intent
+ of the function: to allow the user to abort the running of a S-Lang
+ interpreter function.
+
+ SEE ALSO
+ SLang_init_tty, SLsignal_intr
+--------------------------------------------------------------
+
+SLkm_define_key
+
+ SYNOPSIS
+ Define a key in a keymap
+
+ USAGE
+ int SLkm_define_key (char *seq, FVOID_STAR f, SLKeyMap_List_Type *km)
+
+ DESCRIPTION
+ `SLkm_define_key' associates the key sequence `seq' with the
+ function pointer `f' in the keymap specified by `km'. Upon
+ success, it returns zero, otherwise it returns a negative integer
+ upon error.
+
+ SEE ALSO
+ SLkm_define_keysym, SLang_define_key
+--------------------------------------------------------------
+
+SLang_define_key
+
+ SYNOPSIS
+ Define a key in a keymap
+
+ USAGE
+ int SLang_define_key(char *seq, char *fun, SLKeyMap_List_Type *km)
+
+ DESCRIPTION
+ `SLang_define_key' associates the key sequence `seq' with
+ the function whose name is `fun' in the keymap specified by
+ `km'.
+
+ SEE ALSO
+ SLkm_define_keysym, SLkm_define_key
+--------------------------------------------------------------
+
+SLkm_define_keysym
+
+ SYNOPSIS
+ Define a keysym in a keymap
+
+ USAGE
+ int SLkm_define_keysym (seq, ks, km)
+
+ char *seq;
+ unsigned int ks;
+ SLKeyMap_List_Type *km;
+
+
+ DESCRIPTION
+ `SLkm_define_keysym' associates the key sequence `seq' with
+ the keysym `ks' in the keymap `km'. Keysyms whose value is
+ less than or equal to `0x1000' is reserved by the library and
+ should not be used.
+
+ SEE ALSO
+ SLkm_define_key, SLang_define_key
+--------------------------------------------------------------
+
+SLang_undefine_key
+
+ SYNOPSIS
+ Undefined a key from a keymap
+
+ USAGE
+ void SLang_undefine_key(char *seq, SLKeyMap_List_Type *km);
+
+ DESCRIPTION
+ `SLang_undefine_key' removes the key sequence `seq' from the
+ keymap `km'.
+
+ SEE ALSO
+ SLang_define_key
+--------------------------------------------------------------
+
+SLang_create_keymap
+
+ SYNOPSIS
+ Create a new keymap
+
+ USAGE
+ SLKeyMap_List_Type *SLang_create_keymap (name, km)
+
+ char *name;
+ SLKeyMap_List_Type *km;
+
+
+ DESCRIPTION
+ `SLang_create_keymap' creates a new keymap called `name' by
+ copying the key definitions from the keymap `km'. If `km'
+ is `NULL', the newly created keymap will be empty and it is up
+ to the calling routine to initialize it via the
+ `SLang_define_key' and `SLkm_define_keysym' functions.
+ `SLang_create_keymap' returns a pointer to the new keymap, or
+ `NULL' upon failure.
+
+ SEE ALSO
+ SLang_define_key, SLkm_define_keysym
+--------------------------------------------------------------
+
+SLang_do_key
+
+ SYNOPSIS
+ Read a keysequence and return its keymap entry
+
+ USAGE
+ SLang_Key_Type *SLang_do_key (kml, getkey)
+
+ SLKeyMap_List_Type *kml;
+ int (*getkey)(void);
+
+
+ DESCRIPTION
+ The `SLang_do_key' function reads characters using the function
+ specified by the `getkey' function pointer and uses the
+ key sequence to return the appropriate entry in the keymap specified
+ by `kml'.
+
+ `SLang_do_key' returns `NULL' if the key sequence is not
+ defined by the keymap, otherwise it returns a pointer to an object
+ of type `SLang_Key_Type', which is defined in `slang.h' as
+
+ #define SLANG_MAX_KEYMAP_KEY_SEQ 14
+ typedef struct SLang_Key_Type
+ {
+ struct SLang_Key_Type *next;
+ union
+ {
+ char *s;
+ FVOID_STAR f;
+ unsigned int keysym;
+ }
+ f;
+ unsigned char type; /* type of function */
+ #define SLKEY_F_INTERPRET 0x01
+ #define SLKEY_F_INTRINSIC 0x02
+ #define SLKEY_F_KEYSYM 0x03
+ unsigned char str[SLANG_MAX_KEYMAP_KEY_SEQ + 1];/* key sequence */
+ }
+ SLang_Key_Type;
+
+
+ The `type' field specifies which field of the union `f'
+ should be used. If `type' is `SLKEY_F_INTERPRET', then
+ `f.s' is a string that should be passed to the interpreter for
+ evaluation. If `type' is `SLKEY_F_INTRINSIC', then
+ `f.f' refers to function that should be called. Otherwise,
+ `type' is `SLKEY_F_KEYSYM' and `f.keysym' represents the
+ value of the keysym that is associated with the key sequence.
+
+ SEE ALSO
+ SLkm_define_keysym, SLkm_define_key
+--------------------------------------------------------------
+
+SLang_find_key_function
+
+ SYNOPSIS
+ Obtain a function pointer associated with a keymap
+
+ USAGE
+ FVOID_STAR SLang_find_key_function (fname, km);
+
+ char *fname;
+ SLKeyMap_List_Type *km;
+
+
+ DESCRIPTION
+ The `SLang_find_key_function' routine searches through the
+ `SLKeymap_Function_Type' list of functions associated with the
+ keymap `km' for the function with name `fname'.
+ If a matching function is found, a pointer to the function will
+ be returned, otherwise `SLang_find_key_function' will return
+ `NULL'.
+
+ SEE ALSO
+ SLang_create_keymap, SLang_find_keymap
+--------------------------------------------------------------
+
+SLang_find_keymap
+
+ SYNOPSIS
+ Find a keymap
+
+ USAGE
+ SLKeyMap_List_Type *SLang_find_keymap (char *keymap_name);
+
+ DESCRIPTION
+ The `SLang_find_keymap' function searches through the list of
+ keymaps looking for one whose name is `keymap_name'. If a
+ matching keymap is found, the function returns a pointer to the
+ keymap. It returns `NULL' if no such keymap exists.
+
+ SEE ALSO
+ SLang_create_keymap, SLang_find_key_function
+--------------------------------------------------------------
+
+SLang_process_keystring
+
+ SYNOPSIS
+ Un-escape a key-sequence
+
+ USAGE
+ char *SLang_process_keystring (char *kseq);
+
+ DESCRIPTION
+ The `SLang_process_keystring' function converts an escaped key
+ sequence to its raw form by converting two-character combinations
+ such as `^A' to the _single_ character `Ctrl-A' (ASCII
+ 1). In addition, if the key sequence contains constructs such as
+ `^(XX)', where `XX' represents a two-character termcap
+ specifier, the termcap escape sequence will be looked up and
+ substituted.
+
+ Upon success, `SLang_process_keystring' returns a raw
+ key-sequence whose first character represents the total length of
+ the key-sequence, including the length specifier itself. It returns
+ `NULL' upon failure.
+
+ EXAMPLE
+ Consider the following examples:
+
+ SLang_process_keystring ("^X^C");
+ SLang_process_keystring ("^[[A");
+
+ The first example will return a pointer to a buffer of three characters
+ whose ASCII values are given by `{3,24,3}'. Similarly, the
+ second example will return a pointer to the four characters
+ `{4,27,91,65}'. Finally, the result of
+
+ SLang_process_keystring ("^[^(ku)");
+
+ will depend upon the termcap/terminfo capability `"ku"', which
+ represents the escape sequence associated with the terminal's UP
+ arrow key. For an ANSI terminal whose UP arrow produces
+ `"ESC [ A"', the result will be `5,27,27,91,65'.
+
+ NOTES
+ `SLang_process_keystring' returns a pointer to a static area
+ that will be overwritten on subsequent calls.
+
+ SEE ALSO
+ SLang_define_key, SLang_make_keystring
+--------------------------------------------------------------
+
+SLang_make_keystring
+
+ SYNOPSIS
+ Make a printable key sequence
+
+ USAGE
+ char *SLang_make_keystring (unsigned char *ks);
+
+ DESCRIPTION
+ The `SLang_make_keystring' function takes a raw key sequence
+ `ks' and converts it to a printable form by converting
+ characters such as ASCII 1 (ctrl-A) to `^A'. That is, it
+ performs the opposite function of `SLang_process_keystring'.
+
+ NOTES
+ This function returns a pointer to a static area that will be
+ overwritten on the next call to `SLang_make_keystring'.
+
+ SEE ALSO
+ SLang_process_keystring
+--------------------------------------------------------------
+
+SLextract_list_element
+
+ SYNOPSIS
+ Extract a substring of a delimited string
+
+ USAGE
+ int SLextract_list_element (dlist, nth, delim, buf, buflen)
+
+ char *dlist;
+ unsigned int nth;
+ char delim;
+ char *buf;
+ unsigned int buflen;
+
+
+ DESCRIPTION
+ `SLextract_list_element' may be used to obtain the `nth'
+ element of a list of strings, `dlist', that are delimited by the
+ character `delim'. The routine copies the `nth' element of
+ `dlist' to the buffer `buf' whose size is `buflen'
+ characters. It returns zero upon success, or -1 if `dlist'
+ does not contain an `nth' element.
+
+ EXAMPLE
+ A delimited list of strings may be turned into an array of strings
+ as follows. For conciseness, all malloc error checking has been
+ omitted.
+
+ int list_to_array (char *list, char delim, char ***ap)
+ {
+ unsigned int nth;
+ char **a;
+ char buf[1024];
+
+ /* Determine the size of the array */
+ nth = 0;
+ while (0 == SLextract_list_element (list, nth, delim, buf, sizeof(buf)))
+ nth++;
+
+ ap = (char **) SLmalloc ((nth + 1) * sizeof (char **));
+ nth = 0;
+ while (0 == SLextract_list_element (list, nth, delim, buf, sizeof(buf)))
+ {
+ a[nth] = SLmake_string (buf);
+ nth++;
+ }
+ a[nth] = NULL;
+ *ap = a;
+ return 0;
+ }
+
+
+ SEE ALSO
+ SLmalloc, SLmake_string
+--------------------------------------------------------------
+
+SLprep_open_prep
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLprep_open_prep (SLPreprocess_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLprep_close_prep
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLprep_close_prep (SLPreprocess_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLprep_line_ok
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLprep_line_ok (char *, SLPreprocess_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLdefine_for_ifdef
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLdefine_for_ifdef (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLang_Read_Line_Type * SLang_rline_save_line (SLang_RLine_Info_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ SLang_Read_Line_Type * SLang_rline_save_line (SLang_RLine_Info_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLang_init_readline (SLang_RLine_Info_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLang_init_readline (SLang_RLine_Info_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLang_read_line (SLang_RLine_Info_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLang_read_line (SLang_RLine_Info_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLang_rline_insert (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLang_rline_insert (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLrline_redraw (SLang_RLine_Info_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLrline_redraw (SLang_RLine_Info_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_flush_output (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_flush_output (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_scroll_region(int, int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_scroll_region(int, int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_reset_scroll_region(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_reset_scroll_region(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_reverse_video (int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_reverse_video (int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_bold_video (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_bold_video (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_begin_insert(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_begin_insert(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_end_insert(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_end_insert(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_del_eol(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_del_eol(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_goto_rc (int, int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_goto_rc (int, int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_delete_nlines(int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_delete_nlines(int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_delete_char(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_delete_char(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_erase_line(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_erase_line(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_normal_video(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_normal_video(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_cls(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_cls(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_beep(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_beep(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_reverse_index(int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_reverse_index(int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_smart_puts(unsigned short *, unsigned short *, int, int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_smart_puts(unsigned short *, unsigned short *, int, int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_write_string (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_write_string (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_putchar(char);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_putchar(char);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_init_video (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_init_video (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_reset_video (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_reset_video (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_get_terminfo(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_get_terminfo(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_get_screen_size (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_get_screen_size (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_set_cursor_visibility (int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_set_cursor_visibility (int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_initialize (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_initialize (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_enable_cursor_keys(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_enable_cursor_keys(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_term_vtxxx(int *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_term_vtxxx(int *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_color_esc (int, char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_color_esc (int, char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_wide_width(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_wide_width(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_narrow_width(void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_narrow_width(void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_set_mouse_mode (int, int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_set_mouse_mode (int, int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_alt_char_set (int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_alt_char_set (int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_write_to_status_line (char *, int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_write_to_status_line (char *, int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_disable_status_line (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_disable_status_line (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLtt_tgetstr (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLtt_tgetstr (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_tgetnum (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_tgetnum (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_tgetflag (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_tgetflag (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLtt_tigetent (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLtt_tigetent (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLtt_tigetstr (char *, char **);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLtt_tigetstr (char *, char **);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLtt_tigetnum (char *, char **);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLtt_tigetnum (char *, char **);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLtt_Char_Type SLtt_get_color_object (int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ SLtt_Char_Type SLtt_get_color_object (int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_color_object (int, SLtt_Char_Type);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_color_object (int, SLtt_Char_Type);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_color (int, char *, char *, char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_color (int, char *, char *, char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_mono (int, char *, SLtt_Char_Type);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_mono (int, char *, SLtt_Char_Type);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_add_color_attribute (int, SLtt_Char_Type);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_add_color_attribute (int, SLtt_Char_Type);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLtt_set_color_fgbg (int, SLtt_Char_Type, SLtt_Char_Type);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLtt_set_color_fgbg (int, SLtt_Char_Type, SLtt_Char_Type);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLkp_define_keysym (char *, unsigned int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLkp_define_keysym (char *, unsigned int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLkp_init (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLkp_init (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLkp_getkey (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLkp_getkey (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLscroll_find_top (SLscroll_Window_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLscroll_find_top (SLscroll_Window_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLscroll_find_line_num (SLscroll_Window_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLscroll_find_line_num (SLscroll_Window_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+unsigned int SLscroll_next_n (SLscroll_Window_Type *, unsigned int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ unsigned int SLscroll_next_n (SLscroll_Window_Type *, unsigned int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+unsigned int SLscroll_prev_n (SLscroll_Window_Type *, unsigned int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ unsigned int SLscroll_prev_n (SLscroll_Window_Type *, unsigned int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLscroll_pageup (SLscroll_Window_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLscroll_pageup (SLscroll_Window_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLscroll_pagedown (SLscroll_Window_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLscroll_pagedown (SLscroll_Window_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLSig_Fun_Type *SLsignal (int, SLSig_Fun_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ SLSig_Fun_Type *SLsignal (int, SLSig_Fun_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLSig_Fun_Type *SLsignal_intr (int, SLSig_Fun_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ SLSig_Fun_Type *SLsignal_intr (int, SLSig_Fun_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLsig_block_signals (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLsig_block_signals (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLsig_unblock_signals (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLsig_unblock_signals (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLsystem (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLsystem (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLadd_at_handler (long *, char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLadd_at_handler (long *, char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLang_define_case(int *, int *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLang_define_case(int *, int *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLang_init_case_tables (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLang_init_case_tables (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+unsigned char *SLang_regexp_match(unsigned char *, unsigned int, SLRegexp_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ unsigned char *SLang_regexp_match(unsigned char *, unsigned int, SLRegexp_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLang_regexp_compile (SLRegexp_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLang_regexp_compile (SLRegexp_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLregexp_quote_string (char *, char *, unsigned int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLregexp_quote_string (char *, char *, unsigned int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLcmd_execute_string (char *, SLcmd_Cmd_Table_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLcmd_execute_string (char *, SLcmd_Cmd_Table_Type *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLsearch_init (char *, int, int, SLsearch_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLsearch_init (char *, int, int, SLsearch_Type *);
+
+ DESCRIPTION
+ ??
+ /* This routine must first be called before any search can take place.
+ * The second parameter specifies the direction of the search: greater than
+ * zero for a forwrd search and less than zero for a backward search. The
+ * third parameter specifies whether the search is case sensitive or not.
+ * The last parameter is a pointer to a structure that is filled by this
+ * function and it is this structure that must be passed to SLsearch.
+ */
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+unsigned char *SLsearch (unsigned char *, unsigned char *, SLsearch_Type *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ unsigned char *SLsearch (unsigned char *, unsigned char *, SLsearch_Type *);
+
+ DESCRIPTION
+ ??
+ /* To use this routine, you must first call 'SLsearch_init'. Then the first
+ * two parameters p1 and p2 serve to define the region over which the search
+ * is to take place. The third parameter is the structure that was previously
+ * initialized by SLsearch_init.
+ *
+ * The routine returns a pointer to the match if found otherwise it returns
+ * NULL.
+ */
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+SLcomplex_abs
+
+ SYNOPSIS
+ Returns the norm of a complex number
+
+ USAGE
+ double SLcomplex_abs (double *z)
+
+ DESCRIPTION
+ The `SLcomplex_abs' function returns the absolute value or the
+ norm of the complex number given by `z'.
+
+ SEE ALSO
+ SLcomplex_times
+--------------------------------------------------------------
+
+double *SLcomplex_times (double *, double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_times (double *, double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_divide (double *, double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_divide (double *, double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_sin (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_sin (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_cos (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_cos (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_tan (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_tan (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_asin (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_asin (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_acos (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_acos (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_atan (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_atan (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_exp (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_exp (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_log (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_log (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_log10 (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_log10 (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_sqrt (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_sqrt (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_sinh (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_sinh (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_cosh (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_cosh (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_tanh (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_tanh (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_pow (double *, double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_pow (double *, double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double SLmath_hypot (double x, double y);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double SLmath_hypot (double x, double y);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_acosh (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_acosh (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+double *SLcomplex_atanh (double *, double *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ double *SLcomplex_atanh (double *, double *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLdebug_malloc (unsigned long);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLdebug_malloc (unsigned long);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLdebug_calloc (unsigned long, unsigned long);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLdebug_calloc (unsigned long, unsigned long);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLdebug_realloc (char *, unsigned long);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLdebug_realloc (char *, unsigned long);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLdebug_free (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLdebug_free (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLmalloc_dump_statistics (void);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLmalloc_dump_statistics (void);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLstrcpy(register char *, register char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLstrcpy(register char *, register char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLstrcmp(register char *, register char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLstrcmp(register char *, register char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+char *SLstrncpy(char *, register char *, register int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ char *SLstrncpy(char *, register char *, register int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLmemset (char *, char, int);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLmemset (char *, char, int);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLexpand_escaped_string (register char *, register char *, register char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLexpand_escaped_string (register char *, register char *, register char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+void SLmake_lut (unsigned char *, unsigned char *, unsigned char);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ void SLmake_lut (unsigned char *, unsigned char *, unsigned char);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
+int SLang_guess_type (char *);
+
+ SYNOPSIS
+ ??
+
+ USAGE
+ int SLang_guess_type (char *);
+
+ DESCRIPTION
+ ??
+
+ SEE ALSO
+ ??
+--------------------------------------------------------------
+
diff --git a/libslang/doc/text/cslang.txt b/libslang/doc/text/cslang.txt
new file mode 100644
index 0000000..18eab6a
--- /dev/null
+++ b/libslang/doc/text/cslang.txt
@@ -0,0 +1,2989 @@
+ S-Lang Library C Programmer's Guide, V1.4.9
+ John E. Davis, davis@space.mit.edu
+ Mar 23, 2003
+ ____________________________________________________________
+
+ Table of Contents
+
+ Preface
+
+ 1. A Brief History of S-Lang
+ 2. Acknowledgements
+ 2. Introduction
+ 2. Interpreter Interface
+ 3. Embedding the Interpreter
+ 4. Calling the Interpreter
+ 4.1 Loading Files
+ 4.2 Loading Strings
+
+ 5. Intrinsic Functions
+ 5.1 Restrictions on Intrinsic Functions
+ 5.2 Adding a New Intrinsic
+ 5.3 More Complicated Intrinsics
+
+ 6. Intrinsic Variables
+ 7. Aggregate Data Objects
+ 7.1 Arrays
+ 7.2 Structures
+ 7.2.1 Interpreter Structures
+ 7.2.2 Intrinsic Structures
+ 7.2.2 Keyboard Interface
+
+ 8. Initializing the Keyboard Interface
+ 9. Resetting the Keyboard Interface
+ 10. Initializing the SLkp Routines
+ 11. Setting the Interrupt Handler
+ 12. Reading Keyboard Input with SLang_getkey
+ 13. Reading Keyboard Input with SLkp_getkey
+ 14. Buffering Input
+ 15. Global Variables
+ 15. Screen Management
+ 16. Initialization
+ 17. Resetting SLsmg
+ 18. Handling Screen Resize Events
+ 19. SLsmg Functions
+ 19.1 Positioning the cursor
+ 19.2 Writing to the Display
+ 19.3 Erasing the Display
+ 19.4 Setting Character Attributes
+ 19.5 Lines and Alternate Character Sets
+ 19.6 Miscellaneous Functions
+
+ 20. Variables
+ 21. Hints for using SLsmg
+ 21. Signal Functions
+ 21. Searching Functions
+ 22. Regular Expressions
+ 23. Simple Searches
+ 24. Initialization
+ 25. SLsearch
+ 25. Copyright
+ A. The GNU Public License
+ B. The Artistic License
+
+
+ ______________________________________________________________________
+
+ 1. Preface
+
+
+
+ S-Lang is an interpreted language that was designed from the start to
+ be easily embedded into a program to provide it with a powerful
+ extension language. Examples of programs that use S-Lang as an
+ extension language include the jed text editor, the slrn newsreader,
+ and sldxe (unreleased), a numerical computation program. For this
+ reason, S-Lang does not exist as a separate application and many of
+ the examples in this document are presented in the context of one of
+ the above applications.
+
+ S-Lang is also a programmer's library that permits a programmer to
+ develop sophisticated platform-independent software. In addition to
+ providing the S-Lang extension language, the library provides
+ facilities for screen management, keymaps, low-level terminal I/O,
+ etc. However, this document is concerned only with the extension
+ language and does not address these other features of the S-Lang
+ library. For information about the other components of the library,
+ the reader is referred to the The S-Lang Library Reference.
+
+
+ 1.1. A Brief History of S-Lang
+
+
+
+ I first began working on S-Lang sometime during the fall of 1992. At
+ that time I was writing a text editor (jed), which I wanted to endow
+ with a macro language. It occured to me that an application-
+ independent language that could be embedded into the editor would
+ prove more useful because I could envision embedding it into other
+ programs. As a result, S-Lang was born.
+
+ S-Lang was originally a stack language that supported a postscript-
+ like syntax. For that reason, I named it S-Lang, where the S was
+ supposed to emphasize its stack-based nature. About a year later, I
+ began to work on a preparser that would allow one to write using a
+ more traditional infix syntax making it easier to use for those
+ unfamiliar with stack based languages. Currently, the syntax of the
+ language resembles C, nevertheless some postscript-like features still
+ remain, e.g., the `%' character is still used as a comment delimiter.
+
+
+
+ 1.2. Acknowledgements
+
+
+
+ Since I first released S-Lang, I have received a lot feedback about
+ the library and the language from many people. This has given me the
+ opportunity and pleasure to interact with several people to make the
+ library portable and easy to use. In particular, I would like to
+ thank the following individuals:
+
+ Luchesar Ionkov <lionkov@sf.cit.bg> for his comments and criticisms of
+ the syntax of the language. He was the person who made me realize
+ that the low-level byte-code engine should be totally type-
+ independent. He also improved the tokenizer and preparser and
+ impressed upon me that the language needed a grammar.
+
+ Mark Olesen <olesen@weber.me.queensu.ca> for his many patches to
+ various aspects of the library and his support on AIX. He also
+ contributed a lot to the pre-processing (SLprep) routines.
+
+ John Burnell <j.burnell@irl.cri.nz> for the OS/2 port of the video and
+ keyboard routines. He also made value suggestions regarding the
+ interpreter interface.
+
+ Darrel Hankerson <hankedr@mail.auburn.edu> for cleaning up and
+ unifying some of the code and the makefiles.
+
+ Dominik Wujastyk <ucgadkw@ucl.ac.uk> who was always willing to test
+ new releases of the library.
+
+ Michael Elkins <me@muddcs.cs.hmc.edu> for his work on the curses
+ emulation.
+
+ Ulli Horlacher <framstag@belwue.de> and Oezguer Kesim <kesim@math.fu-
+ berlin.de> for the S-Lang newsgroup and mailing list.
+
+ Hunter Goatley, Andy Harper <Andy.Harper@kcl.ac.uk>, and Martin P.J.
+ Zinser <zinser@decus.decus.de> for their VMS support.
+
+ Dave Sims <sims@usa.acsys.com> and Chin Huang <cthuang@vex.net> for
+ Windows 95 and Windows NT support.
+
+ Lloyd Zusman <ljz@asfast.com> and Rich Roth <rich@on-the-net.com> for
+ creating and maintaining www.s-lang.org.
+
+ I am also grateful to many other people who send in bug-reports and
+ bug-fixes, for without such community involvement, S-Lang would not be
+ as well-tested and stable as it is. Finally, I would like to thank my
+ wife for her support and understanding while I spent long weekend
+ hours developing the library.
+
+
+
+ 2. Introduction
+
+
+
+ S-Lang is a C programmer's library that includes routines for the
+ rapid development of sophisticated, user friendly, multi-platform
+ applications. The S-Lang library includes the following:
+
+
+ o Low level tty input routines for reading single characters at a
+ time.
+
+ o Keymap routines for defining keys and manipulating multiple
+ keymaps.
+
+ o A high-level keyprocessing interface (SLkp) for handling function
+ and arrow keys.
+
+ o High level screen management routines for manipulating both
+ monochrome and color terminals. These routines are very efficient.
+ (SLsmg)
+
+ o Low level terminal-independent routines for manipulating the
+ display of a terminal. (SLtt)
+
+ o Routines for reading single line input with line editing and recall
+ capabilities. (SLrline)
+
+ o Searching functions: both ordinary searches and regular expression
+ searches. (SLsearch)
+
+ o An embedded stack-based language interpreter with a C-like syntax.
+
+
+ The library is currently available for OS/2, MSDOS, Unix, and VMS
+ systems. For the most part, the interface to library routines has
+ been implemented in such a way that it appears to be platform
+ independent from the point of view of the application. In addition,
+ care has been taken to ensure that the routines are ``independent'' of
+ one another as much as possible. For example, although the keymap
+ routines require keyboard input, they are not tied to S-Lang's
+ keyboard input routines--- one can use a different keyboard getkey
+ routine if one desires. This also means that linking to only part of
+ the S-Lang library does not pull the whole library into the
+ application. Thus, S-Lang applications tend to be relatively small in
+ comparison to programs that use libraries with similar capabilities.
+
+
+
+ 3. Interpreter Interface
+
+
+
+ The S-Lang library provides an interpreter that when embedded into an
+ application, makes the application extensible. Examples of programs
+ that embed the interpreter include the jed editor and the slrn
+ newsreader.
+
+ Embedding the interpreter is easy. The hard part is to decide what
+ application specific built-in or intrinsic functions should be
+ provided by the application. The S-Lang library provides some pre-
+ defined intrinsic functions, such as string processing functions, and
+ simple file input-output routines. However, the basic philosophy
+ behind the interpreter is that it is not a standalone program and it
+ derives much of its power from the application that embeds it.
+
+
+ 3.1. Embedding the Interpreter
+
+
+
+ Only one function needs to be called to embed the S-Lang interpreter
+ into an application: SLang_init_slang. This function initializes the
+ interpreter's data structures and adds some intrinsic functions:
+
+
+ if (-1 == SLang_init_slang ())
+ exit (EXIT_FAILURE);
+
+
+
+ This function does not provide file input output intrinsic nor does it
+ provide mathematical functions. To make these as well as some posix
+ system calls available use
+
+
+ if ((-1 == SLang_init_slang ()) /* basic interpreter functions */
+ || (-1 == SLang_init_slmath ()) /* sin, cos, etc... */
+ || (-1 == SLang_init_stdio ()) /* stdio file I/O */
+ || (-1 == SLang_init_posix_dir ()) /* mkdir, stat, etc. */
+ || (-1 == SLang_init_posix_process ()) /* getpid, umask, etc. */
+ )
+ exit (EXIT_FAILURE);
+
+
+
+ If you intend to enable all intrinsic functions, then it is simpler to
+ initialize the interpreter via
+
+
+ if (-1 == SLang_init_all ())
+ exit (EXIT_FAILURE);
+
+
+
+ See the \slang-run-time-library for more information about the intrin-
+ sic functions.
+
+
+
+ 3.2. Calling the Interpreter
+
+
+
+ There are several ways of calling the interpreter. The two most
+ common method is to load a file containing S-Lang code, or to load a
+ string.
+
+
+ 3.2.1. Loading Files
+
+ The SLang_load_file and SLns_load_file functions may be used to
+ interpret a file. Both these functions return zero if successful, or
+ -1 upon failure. If either of these functions fail, the interpreter
+ will accept no more code unless the error state is cleared. This is
+ done by calling SLang_restart function to set the interpreter to its
+ default state, and setting SLang_Error to 0, e.g.,
+
+
+ if (-1 == SLang_load_file ("site.sl"))
+ {
+ /* Clear the error and rest the interpreter */
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+
+
+
+ When a file is loaded via SLang_load_file, any non-public variables
+ and functions defined in the file will be placed into a namespace that
+ is local to the file itself. The SLns_load_file function may be used
+ to load a file using a specified namespace, e.g.,
+
+
+ if (-1 == SLns_load_file ("site.sl", "NS"))
+ {
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+
+
+
+ will load site.sl into a namespace called NS. If such a namespace
+ does not exist, then it will be created.
+
+ Both the SLang_load_file and SLns_load_file functions search for files
+ along an application-specified search path. This path may be set
+ using the SLpath_set_load_path function, as well as from interpeted
+ code via the set_slang_load_path function. By default, no search path
+ is defined.
+
+ Files are searched as follows: If the name begins with the equivalent
+ of "./" or "../", then it is searched for with respect to the current
+ directory, and not along the load-path. If no such file exists, then
+ an error will be generated. Otherwise, the file is searched for in
+ each of the directories of the load-path by concatenating the path
+ element with the specified file name. The first such file found to
+ exist by this process will be loaded. If a matching file still has
+ not been found, and the file name lacks an extension, then the path is
+ searched with ".sl" and ".slc" appended to the filename. If two such
+ files are found (one ending with ".sl" and the other with ".slc"),
+ then the more recent of the two will be used. If no matching file has
+ been found by this process, then the search will cease and an error
+ generated.
+ The search path is a delimiter separated list of directories that
+ specify where the interpreter looks for files. By default, the value
+ of the delimiter is OS-dependent following the convention of the
+ underlying OS. For example, on Unix the delimiter is represented by a
+ colon, on DOS/Windows it is a semi-colon, and on VMS it is a space.
+ The SLpath_set_delimiter and SLpath_get_delimiter may be used to set
+ and query the delimiter's value, respectively.
+
+
+ 3.2.2. Loading Strings
+
+ There are several other mechanisms for interacting with the
+ interpreter. For example, the SLang_load_string function loads a
+ string into the interpreter and interprets it:
+
+
+ if (-1 == SLang_load_string ("message (\"hello\");"))
+ {
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+
+
+
+ Similarly, the SLns_load_string function may be used to load a string
+ into a specified namespace.
+
+ Typically, an interactive application will load a file via
+ SLang_load_file and then go into a loop that consists of reading lines
+ of input and sending them to the interpreter, e.g.,
+
+
+ while (EOF != fgets (buf, sizeof (buf), stdin))
+ {
+ if (-1 == SLang_load_string (buf))
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+
+
+
+ Finally, some applications such as jed and slrn use another method of
+ interacting with the interpreter. They read key sequences from the
+ keyboard and map those key sequences to interpreter functions via the
+ S-Lang keymap interface.
+
+
+
+ 3.3. Intrinsic Functions
+
+
+
+ An intrinsic function is simply a function that is written in C and is
+ made available to the interpreter as a built-in function. For this
+ reason, the words `intrinsic' and `built-in' are often used
+ interchangeably.
+
+ Applications are expected to add application specific functions to the
+ interpreter. For example, jed adds nearly 300 editor-specific
+ intrinsic functions. The application designer should think carefully
+ about what intrinsic functions to add to the interpreter.
+
+
+ 3.3.1. Restrictions on Intrinsic Functions
+
+
+
+ When implementing intrinsic functions, it is necessary to follow a few
+ rules to cooperate with the interpreter.
+
+ The C version of an intrinsic function takes only pointer arguments.
+ This is because when the interpreter calls an intrinsic function, it
+ passes values to the function by reference and not by value. For
+ example, intrinsic with the declarations:
+
+
+ int intrinsic_0 (void);
+ int intrinsic_1 (char *s);
+ void intrinsic_2 (char *s, int *i);
+ void intrinsic_3 (int *i, double *d, double *e);
+
+
+
+ are all valid. However,
+
+
+ int invalid_1 (char *s, int len);
+
+
+
+ is not valid since the len parameter is not a pointer.
+
+ The return value of an intrinsic function must be one of the following
+ types: void, char, short, int, long, double, char *, as well as
+ unsigned versions of the integer types. A function such as
+
+
+ int *invalid (void);
+
+
+
+ is not permitted since int* is not a valid return-type for an intrin-
+ sic function. Any other type of value can be passed back to the
+ interpreter by explicitly pushing the object onto the interpreter's
+ stack via the appropriate "push" function.
+
+ The current implementation limits the number of arguments of an
+ intrinsic function to 7. The "pop" functions can be used to allow the
+ function to take an arbitrary number as seen from an interpreter
+ script.
+
+ Another restriction is that the intrinsic function should regard all
+ its parameters as pointers to constant objects and make no attempt to
+ modify the value to which they point. For example,
+
+
+ void truncate (char *s)
+ {
+ s[0] = 0;
+ }
+
+
+
+ is illegal since the function modifies the string s.
+
+ 3.3.2. Adding a New Intrinsic
+
+
+
+ There are two basic mechanisms for adding an intrinsic function to the
+ interpreter: SLadd_intrinsic_function and SLadd_intrin_fun_table.
+ Functions may be added to a specified namespace via
+ SLns_add_intrinsic_function and SLns_add_intrin_fun_table functions.
+
+ As an specific example, consider a function that will cause the
+ program to exit via the exit C library function. It is not possible
+ to make this function an intrinsic because it does not meet the
+ specifications for an intrinsic function that were described earlier.
+ However, one can call exit from a function that is suitable, e.g.,
+
+
+ void intrin_exit (int *code)
+ {
+ exit (*code);
+ }
+
+
+
+ This function may be made available to the interpreter as an intrinsic
+ via the SLadd_intrinsic_function routine:
+
+
+ if (-1 == SLadd_intrinsic_function ("exit", (FVOID_STAR) intrin_exit,
+ SLANG_VOID_TYPE, 1,
+ SLANG_INT_TYPE))
+ exit (EXIT_FAILURE);
+
+
+
+ This statement basically tells the interpreter that intrin_exit is a
+ function that returns nothing and takes a single argument: a pointer
+ to an integer (SLANG_INT_TYPE). A user can call this function from
+ within the interpreter via
+
+
+ message ("Calling the exit function");
+ exit (0);
+
+
+
+ After printing a message, this will cause the intrin_exit function to
+ execute, which in turn calls exit.
+
+ The most convenient mechanism for adding new intrinsic functions is to
+ create a table of SLang_Intrin_Fun_Type objects and add the table via
+ the SLadd_intrin_fun_table function. The table will look like:
+
+
+
+ SLang_Intrin_Fun_Type My_Intrinsics [] =
+ {
+ /* table entries */
+ MAKE_INTRINSIC_N(...),
+ MAKE_INTRINSIC_N(...),
+ .
+ .
+ MAKE_INTRINSIC_N(...),
+ SLANG_END_INTRIN_FUN_TABLE
+ };
+
+
+
+ Construction of the table entries may be facilitated using a set of
+ MAKE_INTRINSIC macros defined in slang.h. The main macro is called
+ MAKE_INTRINSIC_N and takes 11 arguments:
+
+
+ MAKE_INTRINSIC_N(name, funct-ptr, return-type, num-args,
+ arg-1-type, arg-2-type, ... arg-7-type)
+
+
+
+ Here name is the name of the intrinsic function that the interpreter
+ is to give to the function. func-ptr is a pointer to the intrinsic
+ function taking num-args and returning ret-type. The final 7 argu-
+ ments specifiy the argument types. For example, the intrin_exit
+ intrinsic described above may be added to the table using
+
+
+ MAKE_INTRINSIC_N("exit", intrin_exit, SLANG_VOID_TYPE, 1,
+ SLANG_INT_TYPE, 0,0,0,0,0,0)
+
+
+
+ While MAKE_INTRINSIC_N is the main macro for constructing table
+ entries, slang.h defines other macros that may prove useful. In
+ particular, an entry for the intrin_exit function may also be created
+ using any of the following forms:
+
+
+ MAKE_INTRINSIC_1("exit", intrin_exit, SLANG_VOID_TYPE, SLANG_INT_TYPE)
+ MAKE_INTRINSIC_I("exit", intrin_exit, SLANG_VOID_TYPE)
+
+
+
+ See slang.h for related macros. You are also encouraged to look at,
+ e.g., slang/src/slstd.c for a more extensive examples.
+
+ The table may be added via the SLadd_intrin_fun_table function, e.g.,
+
+
+ if (-1 == SLadd_intrin_fun_table (My_Intrinsics, NULL))
+ {
+ /* an error occurred */
+ }
+
+
+
+ Please note that there is no need to load a given table more than
+ once, and it is considered to be an error on the part of the
+ application it adds the same table multiple times. For performance
+ reasons, no checking is performed by the library to see if a table has
+ already been added.
+
+ Earlier it was mentioned that intrinsics may be added to a specified
+ namespace. To this end, one must first get a pointer to the namespace
+ via the SLns_create_namespace function. The following example
+ illustrates how this function is used to add the My_Intrinsics table
+ to a namespace called my:
+
+
+ SLang_NameSpace_Type *ns = SLns_create_namespace ("my");
+ if (ns == NULL)
+ return -1;
+
+ return SLns_add_intrin_fun_table (ns, My_Intrinsics, "__MY__"));
+
+
+
+ 3.3.3. More Complicated Intrinsics
+
+
+ The intrinsic functions described in the previous example were
+ functions that took a fixed number of arguments. In this section we
+ explore more complex intrinsics such as those that take a variable
+ number of arguments.
+
+ Consider a function that takes two double precision numbers and
+ returns the lesser:
+
+
+ double intrin_min (double *a, double *b)
+ {
+ if (*a < *b) return *a;
+ return *b;
+ }
+
+
+
+ This function may be added to a table of intrinsics using
+
+
+ MAKE_INTRINSIC_2("vmin", intrin_min, SLANG_DOUBLE_TYPE,
+ SLANG_DOUBLE_TYPE, SLANG_DOUBLE_TYPE)
+
+
+
+ It is useful to extend this function to take an arbitray number of
+ arguments and return the lesser. Consider the following variant:
+
+
+
+ double intrin_min_n (int *num_ptr)
+ {
+ double min_value, x;
+ unsigned int num = (unsigned int) *num_ptr;
+
+ if (-1 == SLang_pop_double (&min_value, NULL, NULL))
+ return 0.0;
+ num--;
+
+ while (num > 0)
+ {
+ num--;
+ if (-1 == SLang_pop_double (&x, NULL, NULL))
+ return 0.0;
+ if (x < min_value) min_value = x;
+ }
+ return min_value;
+ }
+
+
+
+ Here the number to compare is passed to the function and the actual
+ numbers are removed from the stack via the SLang_pop_double function.
+ A suitable table entry for it is
+
+
+ MAKE_INTRINSIC_I("vmin", intrin_min_n, SLANG_DOUBLE_TYPE)
+
+
+
+ This function would be used in an interpreter script via a statement
+ such as
+
+
+ variable xmin = vmin (x0, x1, x2, x3, x4, 5);
+
+
+
+ which computes the smallest of 5 values.
+
+ The problem with this intrinsic function is that the user must
+ explicitly specify how many numbers to compare. It would be more
+ convenient to simply use
+
+
+ variable xmin = vmin (x0, x1, x2, x3, x4);
+
+
+
+ An intrinsic function can query the value of the variable
+ SLang_Num_Function_Args to obtain the necessary information:
+
+
+
+ double intrin_min (void)
+ {
+ double min_value, x;
+
+ unsigned int num = SLang_Num_Function_Args;
+
+ if (-1 == SLang_pop_double (&min_value, NULL, NULL))
+ return 0.0;
+ num--;
+
+ while (num > 0)
+ {
+ num--;
+ if (-1 == SLang_pop_double (&x, NULL, NULL))
+ return 0.0;
+ if (x < min_value) min_value = x;
+ }
+ return min_value;
+ }
+
+
+
+ This may be declared as an intrinsic using:
+
+
+ MAKE_INTRINSIC_0("vmin", intrin_min, SLANG_DOUBLE_TYPE)
+
+
+
+ 3.4. Intrinsic Variables
+
+
+
+ It is possible to access an application's global variables from within
+ the interpreter. The current implementation supports the access of
+ variables of type int, char *, and double.
+
+ There are two basic methods of making an intrinsic variable available
+ to the interpreter. The most straight forward method is to use the
+ function SLadd_intrinsic_variable:
+
+
+ int SLadd_intrinsic_variable (char *name, VOID_STAR addr,
+ unsigned char data_type,
+ int read_only);
+
+
+
+ For example, suppose that I is an integer variable, e.g.,
+
+
+ int I;
+
+
+
+ One can make it known to the interpreter as I_Variable via a statement
+ such as
+
+
+ if (-1 == SLadd_intrinsic_variable ("I_Variable", &I,
+ SLANG_INT_TYPE, 0))
+ exit (EXIT_FAILURE);
+
+
+
+ Similarly, if S is declared as
+
+
+ char *S;
+
+
+
+ then
+
+
+ if (-1 == SLadd_intrinsic_variable ("S_Variable", &S,
+ SLANG_STRING_TYPE, 1))
+ exit (EXIT_FAILURE);
+
+
+
+ makes S available as a read-only variable with the name S_Variable.
+ Note that if a pointer variable is made available to the interpreter,
+ its value is managed by the interpreter and not the application. For
+ this reason, it is recommended that such variables be declared as
+ read-only.
+
+ It is important to note that if S were declared as an array of
+ characters, e.g.,
+
+
+ char S[256];
+
+
+
+ then it would not be possible to make it directly available to the
+ interpreter. However, one could create a pointer to it, i.e.,
+
+
+ char *S_Ptr = S;
+
+
+
+ and make S_Ptr available as a read-only variable.
+
+ One should not make the mistake of trying to use the same address for
+ different variables as the following example illustrates:
+
+
+
+ int do_not_try_this (void)
+ {
+ static char *names[3] = {"larry", "curly", "moe"};
+ unsigned int i;
+
+ for (i = 0; i < 3; i++)
+ {
+ int value;
+ if (-1 == SLadd_intrinsic_variable (names[i], (VOID_STAR) &value,
+ SLANG_INT_TYPE, 1))
+ return -1;
+ }
+ return 0;
+ }
+
+
+
+ Not only does this piece of code create intrinsic variables that use
+ the same address, it also uses the address of a local variable that
+ will go out of scope.
+
+ The most convenient method for adding many intrinsic variables to the
+ interpreter is to create an array of SLang_Intrin_Var_Type objects and
+ then add the array via SLadd_intrin_var_table. For example, the array
+
+
+ static SLang_Intrin_Var_Type Intrin_Vars [] =
+ {
+ MAKE_VARIABLE("I_Variable", &I, SLANG_INT_TYPE, 0),
+ MAKE_VARIABLE("S_Variable", &S_Ptr, SLANG_STRING_TYPE, 1),
+ SLANG_END_TABLE
+ };
+
+
+
+ may be added via
+
+
+ if (-1 == SLadd_intrin_var_table (Intrin_Vars, NULL))
+ exit (EXIT_FAILURE);
+
+
+
+ It should be rather obvious that the arguments to the MAKE_VARIABLE
+ macro correspond to the parameters of the SLadd_intrinsic_variable
+ function.
+
+ Finally, variables may be added to a specific namespace via the
+ SLns_add_intrin_var_table and SLns_add_intrinsic_variable functions.
+
+
+
+ 3.5. Aggregate Data Objects
+
+
+ An aggregate data object is an object that can contain more than one
+ data value. The S-Lang interpreter supports several such objects:
+ arrays, structure, and associative arrays. In the following sections,
+ information about interacting with these objects is given.
+
+
+
+ 3.5.1. Arrays
+
+
+ An intrinsic function may interact with an array in several different
+ ways. For example, an intrinsic may create an array and return it.
+ The basic functions for manipulating arrays include:
+
+
+ SLang_create_array
+ SLang_pop_array_of_type
+ SLang_push_array
+ SLang_free_array
+ SLang_get_array_element
+ SLang_set_array_element
+
+
+
+ The use of these functions will be illustrated via a few simple exam-
+ ples.
+
+ The first example shows how to create an return an array of strings to
+ the interpreter. In particular, the names of the four seasons of the
+ year will be returned:
+
+
+ void months_of_the_year (void)
+ {
+ static char *seasons[4] =
+ {
+ "Spring", "Summer", "Autumn", "Winter"
+ };
+ SLang_Array_Type *at;
+ int i, four;
+
+ four = 4;
+ at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &four, 1);
+ if (at == NULL)
+ return;
+
+ /* Now set the elements of the array */
+ for (i = 0; i < 4; i++)
+ {
+ if (-1 == SLang_set_array_element (at, &i, &seasons[i]))
+ {
+ SLang_free_array (at);
+ return;
+ }
+ }
+
+ (void) SLang_push_array (at, 0);
+ SLang_free_array (at);
+ }
+
+
+
+ This example illustrates several points. First of all, the SLang_cre-
+ ate_array function was used to create a 1 dimensional array of 4
+ strings. Since this function could fail, its return value was
+ checked. Then the SLang_set_array_element function was used to set
+ the elements of the newly created array. Note that the address con-
+ taining the value of the array element was passed and not the value of
+ the array element itself. That is,
+
+
+ SLang_set_array_element (at, &i, seasons[i])
+
+
+
+ was not used. The return value from this function was also checked
+ because it too could also fail. Finally, the array was pushed onto
+ the interpreter's stack and then it was freed. It is important to
+ understand why it was freed. This is because arrays are reference-
+ counted. When the array was created, it was returned with a reference
+ count of 1. When it was pushed, the reference count was bumped up to
+ 2. Then since it was nolonger needed by the function,
+ SLang_free_array was called to decrement the reference count back to
+ 1. For convenience, the second argument to SLang_push_array deter-
+ mines whether or not it is to also free the array. So, instead of the
+ two function calls:
+
+
+ (void) SLang_push_array (at, 0);
+ SLang_free_array (at);
+
+
+
+ it is preferable to combine them as
+
+
+ (void) SLang_push_array (at, 1);
+
+
+
+ The second example returns a diagonal array of a specified size to the
+ stack. A diagonal array is a 2-d array with all elements zero except
+ for those along the diagonal, which have a value of one:
+
+
+ void make_diagonal_array (int n)
+ {
+ SLang_Array_Type *at;
+ int dims[2];
+ int i, one;
+
+ dims[0] = dims[1] = n;
+ at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, dims, 2);
+ if (at == NULL)
+ return;
+
+ one = 1;
+ for (i = 0; i < n; i++)
+ {
+ dims[0] = dims[1] = i;
+ if (-1 == SLang_set_array_element (at, dims, &one))
+ {
+ SLang_free_array (at);
+ return;
+ }
+ }
+
+ (void) SLang_push_array (at, 1);
+ }
+
+
+
+ In this example, only the diagonal elements of the array were set.
+ This is bacause when the array was created, all its elements were set
+ to zero.
+
+ Now consider an example that acts upon an existing array. In
+ particular, consider one that computes the trace of a 2-d matrix,
+ i.e., the sum of the diagonal elements:
+
+
+ double compute_trace (void)
+ {
+ SLang_Array_Type *at;
+ double trace;
+ int dims[2];
+
+ if (-1 == SLang_pop_array_of_type (&at, SLANG_DOUBLE_TYPE))
+ return 0.0;
+
+ /* We want a 2-d square matrix. If the matrix is 1-d and has only one
+ element, then return that element. */
+ trace = 0.0;
+ if (((at->num_dims == 1) && (at->dims[0] == 1))
+ || ((at->num_dims == 2) && (at->dims[0] == at->dims[1])))
+ {
+ double dtrace;
+ int n = at->dims[0];
+
+ for (i = 0; i < n; i++)
+ {
+ dims[0] = dims[1] = i;
+ (void) SLang_get_array_element (at, &dims, &dtrace);
+ trace += dtrace;
+ }
+ }
+ else SLang_verror (SL_TYPE_MISMATCH, "Expecting a square matrix");
+
+ SLang_free_array (at);
+ return trace;
+ }
+
+
+
+ In this example, SLang_pop_array_of_type was used to pop an array of
+ doubles from the stack. This function will make implicit typecasts in
+ order to return an array of the requested type.
+
+
+
+ 3.5.2. Structures
+
+
+
+ For the purposes of this section, we shall differentiate structures
+ according to whether or not they correspond to an application defined
+ C structure. Those that do are called intrinsic structures, and those
+ do not are called S-Lang interpreter structures.
+
+
+ 3.5.2.1. Interpreter Structures
+
+
+ The following simple example shows one method that may be used to
+ create and return a structure with a string and integer field to the
+ interpreter's stack:
+
+ int push_struct_example (char *string_value, int int_value)
+ {
+ char *field_names[2];
+ unsigned char field_types[2];
+ VOID_STAR field_values[2];
+
+ field_names[0] = "string_field";
+ field_types[0] = SLANG_STRING_TYPE;
+ field_values[0] = &string_value;
+
+ field_names[1] = "int_field";
+ field_types[1] = SLANG_INT_TYPE;
+ field_values[1] = &int_value;
+
+ if (-1 == SLstruct_create_struct (2, field_names,
+ field_types, field_values))
+ return -1;
+ return 0;
+ }
+
+
+
+ Here, SLstruct_create_struct is used to push a structure with the
+ specified field names and values onto the interpreter's stack.
+
+ A simpler mechanism exists provided that one has already defined a C
+ structure with a description of how the structure is laid out. For
+ example, consider a C structure defined by
+
+
+ typedef struct
+ {
+ char *s;
+ int i;
+ }
+ SI_Type;
+
+
+
+ Its layout may be specified via a table of SLang_CStruct_Field_Type
+ entries:
+
+
+ SLang_CStruct_Field_Type SI_Type_Layout [] =
+ {
+ MAKE_CSTRUCT_FIELD(SI_Type, s, "string_field", SLANG_STRING_TYPE, 0),
+ MAKE_CSTRUCT_FIELD(SI_Type, i, "int_field", SLANG_INT_TYPE, 0),
+ SLANG_END_CSTRUCT_TABLE
+ };
+
+
+
+ Here, MAKE_CSTRUCT_FIELD is a macro taking 5 arguments:
+
+
+ MAKE_CSTRUCT_FIELD(C-structure-type,
+ C-field-name,
+ slang-field-name,
+ slang-data-type,
+ is-read-only)
+
+
+
+ The first argument is the structure type, the second is the name of a
+ field of the structure, the third is a string that specifies the name
+ of the corresponding field of the S-Lang structure, the fourth argu-
+ ment specifies the field's type, and the last argument specifies
+ whether or not the field should be regarded as read-only.
+
+ Once the layout of the structure has been specified, pushing a S-Lang
+ version of the structure is trival:
+
+
+ int push_struct_example (char *string_value, int int_value)
+ {
+ SI_Type si;
+
+ si.s = string_value;
+ si.i = int_value;
+ return SLang_push_cstruct ((VOID_STAR)&si, SI_Type_Layout);
+ }
+
+
+
+ This mechanism of structure creation also permits a S-Lang structure
+ to be passed to an intrinsic function through the use of the
+ SLang_pop_cstruct routine, e.g.,
+
+
+ void print_si_struct (void)
+ {
+ SI_Type si;
+ if (-1 == SLang_pop_cstruct ((VOID_STAR)&si, SI_Type_Layout))
+ return;
+ printf ("si.i=%d", si.i);
+ printf ("si.s=%s", si.s);
+ SLang_free_cstruct ((VOID_STAR)&si, SI_Type_Layout);
+ }
+
+
+
+ Assuming print_si_struct exists as an intrinsic function, the S-Lang
+ code
+
+
+ variable s = struct {string_field, int_field};
+ s.string_field = "hello";
+ s.int_field = 20;
+ print_si_struct (s);
+
+
+
+ would result in the display of
+
+
+ si.i=20;
+ si.s=hello
+
+
+
+ Note that the SLang_free_cstruct function was called after the con-
+ tents of si were nolonger needed. This was necessary because
+ SLang_pop_cstruct allocated memory to set the char *s field of si.
+ Calling SLang_free_cstruct frees up such memory.
+
+ Now consider the following:
+
+
+ typedef struct
+ {
+ pid_t pid;
+ gid_t group;
+ }
+ X_t;
+
+
+
+ How should the layout of this structure be defined? One might be
+ tempted to use:
+
+
+ SLang_CStruct_Field_Type X_t_Layout [] =
+ {
+ MAKE_CSTRUCT_FIELD(X_t, pid, "pid", SLANG_INT_TYPE, 0),
+ MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_INT_TYPE, 0),
+ SLANG_END_CSTRUCT_TABLE
+ };
+
+
+
+ However, this assumes pid_t and gid_t have been typedefed as ints.
+ But what if gid_t is a short? In such a case, using
+
+
+ MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_SHORT_TYPE, 0),
+
+
+
+ would be the appropriate entry for the group field. Of course, one
+ has no way of knowing how gid_t is declared on other systems. For
+ this reason, it is preferable to use the MAKE_CSTRUCT_INT_FIELD macro
+ in cases involving integer valued fields, e.g.,
+
+
+ SLang_CStruct_Field_Type X_t_Layout [] =
+ {
+ MAKE_CSTRUCT_INT_FIELD(X_t, pid, "pid", 0),
+ MAKE_CSTRUCT_INT_FIELD(X_t, group, "group", 0),
+ SLANG_END_CSTRUCT_TABLE
+ };
+
+
+
+ Before leaving this section, it is important to mention that access to
+ character array fields is not permitted via this interface. That is,
+ a structure such as
+
+
+ typedef struct
+ {
+ char name[32];
+ }
+ Name_Type;
+
+
+
+ is not supported since char name[32] is not a SLANG_STRING_TYPE
+ object. Always keep in mind that a SLANG_STRING_TYPE object is a char
+ *.
+
+
+ 3.5.2.2. Intrinsic Structures
+
+
+ Here we show how to make intrinsic structures available to the
+ interpreter.
+
+ The simplest interface is to structure pointers and not to the actual
+ structures themselves. The latter would require the interpreter to be
+ involved with the creation and destruction of the structures. Dealing
+ with the pointers themselves is far simpler.
+
+ As an example, consider an object such as
+
+
+ typedef struct _Window_Type
+ {
+ char *title;
+ int row;
+ int col;
+ int width;
+ int height;
+ } Window_Type;
+
+
+
+ which defines a window object with a title, size (width, height), and
+ location (row, col).
+
+ We can make variables of type Window_Type available to the interpreter
+ via a table as follows:
+
+
+ static SLang_IStruct_Field_Type Window_Type_Field_Table [] =
+ {
+ MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 1),
+ MAKE_ISTRUCT_FIELD(Window_Type, row, "row", SLANG_INT_TYPE, 0),
+ MAKE_ISTRUCT_FIELD(Window_Type, col, "col", SLANG_INT_TYPE, 0),
+ MAKE_ISTRUCT_FIELD(Window_Type, width, "width", SLANG_INT_TYPE, 0),
+ MAKE_ISTRUCT_FIELD(Window_Type, height, "height", SLANG_INT_TYPE, 0),
+ SLANG_END_ISTRUCT_TABLE
+ };
+
+
+
+ More precisely, this defines the layout of the Window_Type structure.
+ Here, the title has been declared as a read-only field. Using
+
+
+ MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 0),
+
+
+
+ would allow read-write access.
+
+ Now suppose that My_Window is a pointer to a Window_Type object, i.e.,
+
+
+
+ Window_Type *My_Window;
+
+
+
+ We can make this variable available to the interpreter via the
+ SLadd_istruct_table function:
+
+
+ if (-1 == SLadd_istruct_table (Window_Type_Field_Table,
+ (VOID_STAR) &My_Window,
+ "My_Win"))
+ exit (1);
+
+
+
+ This creates a S-Lang interpreter variable called My_Win whose value
+ corresponds to the My_Win structure. This would permit one to access
+ the fields of My_Window via S-Lang statements such as
+
+
+ define set_width_and_height (w,h)
+ {
+ My_Win.width = w;
+ My_Win.height = h;
+ }
+
+
+
+ It is extremely important to understand that the interface described
+ in this section does not allow the interpreter to create new instances
+ of Window_Type objects. The interface merely defines an association
+ or correspondence between an intrinsic structure pointer and a S-Lang
+ variable. For example, if the value of My_Window is NULL, then My_Win
+ would also be NULL.
+
+ One should be careful in allowing read/write access to character
+ string fields. If read/write access is allowed, then the application
+ should always use the SLang_create_slstring and SLang_free_slstring
+ functions to set the character string field of the structure.
+
+
+
+ 4. Keyboard Interface
+
+
+
+ S-Lang's keyboard interface has been designed to allow an application
+ to read keyboard input from the user in a system-independent manner.
+ The interface consists of a set of low routines for reading single
+ character data as well as a higher level interface (SLkp) which
+ utilize S-Lang's keymap facility for reading multi-character
+ sequences.
+
+ To initialize the interface, one must first call the function
+ SLang_init_tty. Before exiting the program, the function
+ SLang_reset_tty must be called to restore the keyboard interface to
+ its original state. Once initialized, the low-level SLang_getkey
+ function may be used to read simgle keyboard characters from the
+ terminal. An application using the higher-level SLkp interface will
+ read charcters using the SLkp_getkey function.
+
+ In addition to these basic functions, there are also functions to
+ ``unget'' keyboard characters, flush the input, detect pending-input
+ with a timeout, etc. These functions are defined below.
+
+
+
+ 4.1. Initializing the Keyboard Interface
+
+
+
+ The function SLang_init_tty must be called to initialize the terminal
+ for single character input. This puts the terminal in a mode usually
+ referred to as ``raw'' mode.
+
+ The prototype for the function is:
+
+
+ int SLang_init_tty (int abort_char, int flow_ctrl, int opost);
+
+
+
+ It takes three parameters that are used to specify how the terminal is
+ to be initialized.
+
+ The first parameter, abort_char, is used to specify the interrupt
+ character (SIGINT). Under MSDOS, this value corresponds to the scan
+ code of the character that will be used to generate the interrupt.
+ For example, under MSDOS, 34 should be used to make Ctrl-G generate an
+ interrupt signal since 34 is the scan code for G. On other systems,
+ the value of abort_char will simply be the ascii value of the control
+ character that will be used to generate the interrupt signal, e.g., 7
+ for Ctrl-G. If -1 is passed, the interrupt character will not be
+ changed.
+
+ Pressing the interrupt character specified by the first argument will
+ generate a signal (SIGINT) that may or not be caught by the
+ application. It is up to the application to catch this signal. S-
+ Lang provides the function Slang_set_abort_signal to make it easy to
+ facilitate this task.
+
+ The second parameter is used to specify whether or not flow control
+ should be used. If this parameter is zero, flow control is enabled
+ otherwise it is disabled. Disabling flow control is necessary to pass
+ certain characters to the application (e.g., Ctrl-S and Ctrl-Q). For
+ some systems such as MSDOS, this parameter is meaningless.
+
+ The third parameter, opost, is used to turn output processing on or
+ off. If opost is zero, output processing is not turned on otherwise,
+ output processing is turned on.
+
+ The SLang_init_tty function returns -1 upon failure. In addition,
+ after it returns, the S-Lang global variable SLang_TT_Baud_Rate will
+ be set to the baud rate of the terminal if this value can be
+ determined.
+
+ Example:
+
+
+ if (-1 == SLang_init_tty (7, 0, 0)) /* For MSDOS, use 34 as scan code */
+ {
+ fprintf (stderr, "Unable to initialize the terminal.\n");
+ exit (1);
+ }
+ SLang_set_abort_signal (NULL);
+
+
+
+ Here the terminal is initialized such that flow control and output
+ processing are turned off. In addition, the character Ctrl-G (-- For
+ MSDOS systems, use the scan code 34 instead of 7 for Ctrl-G--) has
+ been specified to be the interrupt character. The function
+ SLang_set_abort_signal is used to install the default S-Lang interrupt
+ signal handler.
+
+
+
+ 4.2. Resetting the Keyboard Interface
+
+
+
+ The function SLang_reset_tty must be called to reset the terminal to
+ the state it was in before the call to SLang_init_tty. The prototype
+ for this function is:
+
+
+ void SLang_reset_tty (void);
+
+
+
+ Usually this function is only called before the program exits. How-
+ ever, if the program is suspended it should also be called just before
+ suspension.
+
+
+
+ 4.3. Initializing the SLkp Routines
+
+
+
+ Extra initialization of the higher-level SLkp functions are required
+ because they are layered on top of the lower level routines. Since
+ the SLkp_getkey function is able to process function and arrow keys in
+ a terminal independent manner, it is necessary to call the
+ SLtt_get_terminfo function to get information about the escape
+ character sequences that the terminal's function keys send. Once that
+ information is available, the SLkp_init function can construct the
+ proper keymaps to process the escape sequences.
+
+ This part of the initialization process for an application using this
+ interface will look something like:
+
+
+
+ SLtt_get_terminfo ();
+ if (-1 == SLkp_init ())
+ {
+ SLang_doerror ("SLkp_init failed.");
+ exit (1);
+ }
+ if (-1 == SLang_init_tty (-1, 0, 1))
+ {
+ SLang_doerror ("SLang_init_tty failed.");
+ exit (1);
+ }
+
+
+
+ It is important to check the return status of the SLkp_init function
+ which can failed if it cannot allocate enough memory for the keymap.
+
+
+
+ 4.4. Setting the Interrupt Handler
+
+
+
+ The function SLang_set_abort_signal may be used to associate an
+ interrupt handler with the interrupt character that was previously
+ specified by the SLang_init_tty function call. The prototype for this
+ function is:
+
+
+ void SLang_set_abort_signal (void (*)(int));
+
+
+
+ This function returns nothing and takes a single parameter which is a
+ pointer to a function taking an integer value and returning void. If
+ a NULL pointer is passed, the default S-Lang interrupt handler will be
+ used. The S-Lang default interrupt handler under Unix looks like:
+
+
+ static void default_sigint (int sig)
+ {
+ SLsignal_intr (SIGINT, default_sigint);
+ SLKeyBoard_Quit = 1;
+ if (SLang_Ignore_User_Abort == 0) SLang_Error = USER_BREAK;
+ }
+
+
+
+ It simply sets the global variable SLKeyBoard_Quit to one and if the
+ variable SLang_Ignore_User_Abort is non-zero, SLang_Error is set to
+ indicate a user break condition. (The function SLsignal_intr is simi-
+ lar to the standard C signal function except that it will interrupt
+ system calls. Some may not like this behavior and may wish to call
+ this SLang_set_abort_signal with a different handler.)
+ Although the function expressed above is specific to Unix, the
+ analogous routines for other operating systems are equivalent in
+ functionality even though the details of the implementation may vary
+ drastically (e.g., under MSDOS, the hardware keyboard interrupt int 9h
+ is hooked).
+
+
+
+ 4.5. Reading Keyboard Input with SLang_getkey
+
+
+
+ After initializing the keyboard via SLang_init_tty, the S-Lang
+ function SLang_getkey may be used to read characters from the terminal
+ interface. In addition, the function SLang_input_pending may be used
+ to determine whether or not keyboard input is available to be read.
+
+ These functions have prototypes:
+
+
+ unsigned int SLang_getkey (void);
+ int SLang_input_pending (int tsecs);
+
+
+
+ The SLang_getkey function returns a single character from the termi-
+ nal. Upon failure, it returns 0xFFFF. If the interrupt character
+ specified by the SLang_init_tty function is pressed while this func-
+ tion is called, the function will return the value of the interrupt
+ character and set the S-Lang global variable SLKeyBoard_Quit to a non-
+ zero value. In addition, if the default S-Lang interrupt handler has
+ been specified by a NULL argument to the SLang_set_abort_signal func-
+ tion, the global variable SLang_Error will be set to USER_BREAK unless
+ the variable SLang_Ignore_User_Abort is non-zero.
+
+ The SLang_getkey function waits until input is available to be read.
+ The SLang_input_pending function may be used to determine whether or
+ not input is ready. It takes a single parameter that indicates the
+ amount of time to wait for input before returning with information
+ regarding the availability of input. This parameter has units of one
+ tenth (1/10) of a second, i.e., to wait one second, the value of the
+ parameter should be 10. Passing a value of zero causes the function
+ to return right away. SLang_input_pending returns a positive integer
+ if input is available or zero if input is not available. It will
+ return -1 if an error occurs.
+
+ Here is a simple example that reads keys from the terminal until one
+ presses Ctrl-G or until 5 seconds have gone by with no input:
+
+
+
+ #include <stdio.h>
+ #include "slang.h"
+ int main ()
+ {
+ int abort_char = 7; /* For MSDOS, use 34 as scan code */
+ unsigned int ch;
+
+ if (-1 == SLang_init_tty (abort_char, 0, 1))
+ {
+ fprintf (stderr, "Unable to initialize the terminal.\n");
+ exit (-1);
+ }
+ SLang_set_abort_signal (NULL);
+ while (1)
+ {
+ fputs ("\nPress any key. To quit, press Ctrl-G: ", stdout);
+ fflush (stdout);
+ if (SLang_input_pending (50) == 0) /* 50/10 seconds */
+ {
+ fputs ("Waited too long! Bye\n", stdout);
+ break;
+ }
+
+ ch = SLang_getkey ();
+ if (SLang_Error == USER_BREAK)
+ {
+ fputs ("Ctrl-G pressed! Bye\n", stdout);
+ break;
+ }
+ putc ((int) ch, stdout);
+ }
+ SLang_reset_tty ();
+ return 0;
+ }
+
+
+
+ 4.6. Reading Keyboard Input with SLkp_getkey
+
+
+
+ Unlike the low-level function SLang_getkey, the SLkp_getkey function
+ can read a multi-character sequence associated with function keys.
+ The SLkp_getkey function uses SLang_getkey and S-Lang's keymap
+ facility to process escape sequences. It returns a single integer
+ which describes the key that was pressed:
+
+
+ int SLkp_getkey (void);
+
+
+
+ That is, the SLkp_getkey function simple provides a mapping between
+ keys and integers. In this context the integers are called keysyms.
+
+ For single character input such as generated by the a key on the
+ keyboard, the function returns the character that was generated, e.g.,
+ 'a'. For single characters, SLkp_getkey will always return an keysym
+ whose value ranges from 0 to 256. For keys that generate multiple
+ character sequences, e.g., a function or arrow key, the function
+ returns an keysym whose value is greater that 256. The actual values
+ of these keysyms are represented as macros defined in the slang.h
+ include file. For example, the up arrow key corresponds to the keysym
+ whose value is SL_KEY_UP.
+
+ Since it is possible for the user to enter a character sequence that
+ does not correspond to any key. If this happens, the special keysym
+ SL_KEY_ERR will be returned.
+
+ Here is an example of how SLkp_getkey may be used by a file viewer:
+
+
+ switch (SLkp_getkey ())
+ {
+ case ' ':
+ case SL_KEY_NPAGE:
+ next_page ();
+ break;
+ case 'b':
+ case SL_KEY_PPAGE:
+ previous_page ();
+ break;
+ case '\r':
+ case SL_KEY_DOWN:
+ next_line ();
+ break;
+ .
+ .
+ case SL_KEY_ERR:
+ default:
+ SLtt_beep ();
+ }
+
+
+
+ Unlike its lower-level counterpart, SLang_getkey, there do not yet
+ exist any functions in the library that are capable of ``ungetting''
+ keysyms. In particular, the SLang_ungetkey function will not work.
+
+
+
+ 4.7. Buffering Input
+
+
+
+ S-Lang has several functions pushing characters back onto the input
+ stream to be read again later by SLang_getkey. It should be noted
+ that none of the above functions are designed to push back keysyms
+ read by the SLkp_getkey function. These functions are declared as
+ follows:
+
+
+ void SLang_ungetkey (unsigned char ch);
+ void SLang_ungetkey_string (unsigned char *buf, int buflen);
+ void SLang_buffer_keystring (unsigned char *buf, int buflen);
+
+
+
+ SLang_ungetkey is the most simple of the three functions. It takes a
+ single character a pushes it back on to the input stream. The next
+ call to SLang_getkey will return this character. This function may be
+ used to peek at the character to be read by first reading it and then
+ putting it back.
+ SLang_ungetkey_string has the same function as SLang_ungetkey except
+ that it is able to push more than one character back onto the input
+ stream. Since this function can push back null (ascii 0) characters,
+ the number of characters to push is required as one of the parameters.
+
+ The last of these three functions, SLang_buffer_keystring can handle
+ more than one charater but unlike the other two, it places the
+ characters at the end of the keyboard buffer instead of at the
+ beginning.
+
+ Note that the use of each of these three functions will cause
+ SLang_input_pending to return right away with a non-zero value.
+
+ Finally, the S-Lang keyboard interface includes the function
+ SLang_flush_input with prototype
+
+
+ void SLang_flush_input (void);
+
+
+
+ It may be used to discard all input.
+
+ Here is a simple example that looks to see what the next key to be
+ read is if one is available:
+
+
+ int peek_key ()
+ {
+ int ch;
+ if (SLang_input_pending (0) == 0) return -1;
+ ch = SLang_getkey ();
+ SLang_ungetkey (ch);
+ return ch;
+ }
+
+
+
+ 4.8. Global Variables
+
+
+ Although the following S-Lang global variables have already been
+ mentioned earlier, they are gathered together here for completeness.
+
+ int SLang_Ignore_User_Abort; If non-zero, pressing the interrupt
+ character will not result in SLang_Error being set to USER_BREAK.
+
+ volatile int SLKeyBoard_Quit; This variable is set to a non-zero value
+ when the interrupt character is pressed. If the interrupt character is
+ pressed when SLang_getkey is called, the interrupt character will be
+ returned from SLang_getkey.
+
+ int SLang_TT_Baud_Rate; On systems which support it, this variable is
+ set to the value of the terminal's baud rate after the call to
+ SLang_init_tty.
+
+
+
+ 5. Screen Management
+
+
+
+ The S-Lang library provides two interfaces to terminal independent
+ routines for manipulating the display on a terminal. The highest
+ level interface, known as the SLsmg interface is discussed in this
+ section. It provides high level screen management functions more
+ manipulating the display in an optimal manner and is similar in spirit
+ to the curses library. The lowest level interface, or the SLtt
+ interface, is used by the SLsmg routines to actually perform the task
+ of writing to the display. This interface is discussed in another
+ section. Like the keyboard routines, the SLsmg routines are platform
+ independent and work the same on MSDOS, OS/2, Unix, and VMS.
+
+ The screen management, or SLsmg, routines are initialized by function
+ SLsmg_init_smg. Once initialized, the application uses various SLsmg
+ functions to write to a virtual display. This does not cause the
+ physical terminal display to be updated immediately. The physical
+ display is updated to look like the virtual display only after a call
+ to the function SLsmg_refresh. Before exiting, the application using
+ these routines is required to call SLsmg_reset_smg to reset the
+ display system.
+
+ The following subsections explore S-Lang's screen management system in
+ greater detail.
+
+
+ 5.1. Initialization
+
+
+ The function SLsmg_init_smg must be called before any other SLsmg
+ function can be used. It has the simple prototype:
+
+
+ int SLsmg_init_smg (void);
+
+
+
+ It returns zero if successful or -1 if it cannot allocate space for
+ the virtual display.
+
+ For this routine to properly initialize the virtual display, the
+ capabilities of the terminal must be known as well as the size of the
+ physical display. For these reasons, the lower level SLtt routines
+ come into play. In particular, before the first call to
+ SLsmg_init_smg, the application is required to call the function
+ SLtt_get_terminfo before calling SLsmg_init_smg.
+
+ The SLtt_get_terminfo function sets the global variables
+ SLtt_Screen_Rows and SLtt_Screen_Cols to the values appropriate for
+ the terminal. It does this by calling the SLtt_get_screen_size
+ function to query the terminal driver for the appropriate values for
+ these variables. From this point on, it is up to the application to
+ maintain the correct values for these variables by calling the
+ SLtt_get_screen_size function whenever the display size changes, e.g.,
+ in response to a SIGWINCH signal. Finally, if the application is going
+ to read characters from the keyboard, it is also a good idea to
+ initialize the keyboard routines at this point as well.
+
+
+ 5.2. Resetting SLsmg
+
+
+
+ Before the program exits or suspends, the function SLsmg_reset_tty
+ should be called to shutdown the display system. This function has
+ the prototype
+
+
+ void SLsmg_reset_smg (void);
+
+
+
+ This will deallocate any memory allocated for the virtual screen and
+ reset the terminal's display.
+
+ Basically, a program that uses the SLsmg screen management functions
+ and S-Lang's keyboard interface will look something like:
+
+
+ #include "slang.h"
+ int main ()
+ {
+ SLtt_get_terminfo ();
+ SLang_init_tty (-1, 0, 0);
+ SLsmg_init_smg ();
+
+ /* do stuff .... */
+
+ SLsmg_reset_smg ();
+ SLang_reset_tty ();
+ return 0;
+ }
+
+
+
+ If this program is compiled and run, all it will do is clear the
+ screen and position the cursor at the bottom of the display. In the
+ following sections, other SLsmg functions will be introduced which may
+ be used to make this simple program do much more.
+
+
+ 5.3. Handling Screen Resize Events
+
+ The function SLsmg_reinit_smg is designed to be used in conjunction
+ with resize events.
+
+ Under Unix-like operating systems, when the size of the display
+ changes, the application will be sent a SIGWINCH signal. To properly
+ handle this signal, the SLsmg routines must be reinitialized to use
+ the new display size. This may be accomplished by calling
+ SLtt_get_screen_size to get the new size, followed by SLsmg_reinit_smg
+ to reinitialize the SLsmg interface to use the new size. Keep in mind
+ that these routines should not be called from within the signal
+ handler. The following code illustrates the main ideas involved in
+ handling such events:
+
+
+
+ static volatile int Screen_Size_Changed;
+ static sigwinch_handler (int sig)
+ {
+ Screen_Size_Changed = 1;
+ SLsignal (SIGWINCH, sigwinch_handler);
+ }
+
+ int main (int argc, char **argv)
+ {
+ SLsignal (SIGWINCH, sigwinch_handler);
+ SLsmg_init_smg ();
+ .
+ .
+ /* Now enter main loop */
+ while (not_done)
+ {
+ if (Screen_Size_Changed)
+ {
+ SLtt_get_screen_size ();
+ SLsmg_reinit_smg ();
+ redraw_display ();
+ }
+ .
+ .
+ }
+ return 0;
+ }
+
+
+
+ 5.4. SLsmg Functions
+
+
+
+ In the previous sections, functions for initializing and shutting down
+ the SLsmg routines were discussed. In this section, the rest of the
+ SLsmg functions are presented. These functions act only on the
+ virtual display. The physical display is updated when the
+ SLsmg_refresh function is called and not until that time. This
+ function has the simple prototype:
+
+
+ void SLsmg_refresh (void);
+
+
+
+ 5.4.1. Positioning the cursor
+
+
+ The SLsmg_gotorc function is used to position the cursor at a given
+ row and column. The prototype for this function is:
+
+
+ void SLsmg_gotorc (int row, int col);
+
+
+
+ The origin of the screen is at the top left corner and is given the
+ coordinate (0, 0), i.e., the top row of the screen corresponds to row
+ = 0 and the first column corresponds to col = 0. The last row of the
+ screen is given by row = SLtt_Screen_Rows - 1.
+
+ It is possible to change the origin of the coordinate system by using
+ the function SLsmg_set_screen_start with prototype:
+
+
+ void SLsmg_set_screen_start (int *r, int *c);
+
+
+
+ This function takes pointers to the new values of the first row and
+ first column. It returns the previous values by modifying the values
+ of the integers at the addresses specified by the parameter list. A
+ NULL pointer may be passed to indicate that the origin is to be set to
+ its initial value of 0. For example,
+
+
+ int r = 10;
+ SLsmg_set_screen_start (&r, NULL);
+
+
+
+ sets the origin to (10, 0) and after the function returns, the vari-
+ able r will have the value of the previous row origin.
+
+
+ 5.4.2. Writing to the Display
+
+
+ SLsmg has several routines for outputting text to the virtual display.
+ The following points should be understood:
+
+ o The text is output at the position of the cursor of the virtual
+ display and the cursor is advanced to the position that corresponds
+ to the end of the text.
+
+
+ o Text does not wrap at the boundary of the display--- it is
+ trucated. This behavior seems to be more useful in practice since
+ most programs that would use screen management tend to be line
+ oriented.
+
+
+ o Control characters are displayed in a two character sequence
+ representation with ^ as the first character. That is, Ctrl-X is
+ output as ^X.
+
+
+ o The newline character does not cause the cursor to advance to the
+ next row. Instead, when a newline character is encountered when
+ outputting text, the output routine will return. That is,
+ outputting a string containing a newline character will only
+ display the contents of the string up to the newline character.
+
+
+ Although the some of the above items might appear to be too
+ restrictive, in practice this is not seem to be the case. In fact,
+ the design of the output routines was influenced by their actual use
+ and modified to simplify the code of the application utilizing them.
+
+ void SLsmg_write_char (char ch); Write a single character to the
+ virtual display.
+
+
+ void SLsmg_write_nchars (char *str, int len); Write len characters
+ pointed to by str to the virtual display.
+
+ void SLsmg_write_string (char *str); Write the null terminated string
+ given by pointer str to the virtual display. This function is a
+ wrapper around SLsmg_write_nchars.
+
+ void SLsmg_write_nstring (char *str, int n); Write the null terminated
+ string given by pointer str to the virtual display. At most, only n
+ characters are written. If the length of the string is less than n,
+ then the string will be padded with blanks. This function is a
+ wrapper around SLsmg_write_nchars.
+
+ void SLsmg_printf (char *fmt, ...); This function is similar to printf
+ except that it writes to the SLsmg virtual display.
+
+ void SLsmg_vprintf (char *, va_list); Like SLsmg_printf but uses a
+ variable argument list.
+
+
+ 5.4.3. Erasing the Display
+
+
+ The following functions may be used to fill portions of the display
+ with blank characters. The attributes of blank character are the
+ current attributes. (See below for a discussion of character
+ attributes)
+
+ void SLsmg_erase_eol (void); Erase line from current position to the
+ end of the line.
+
+ void SLsmg_erase_eos (void); Erase from the current position to the
+ end of the screen.
+
+ void SLsmg_cls (void); Clear the entire virtual display.
+
+
+ 5.4.4. Setting Character Attributes
+
+
+ Character attributes define the visual characteristics the character
+ possesses when it is displayed. Visual characteristics include the
+ foreground and background colors as well as other attributes such as
+ blinking, bold, and so on. Since SLsmg takes a different approach to
+ this problem than other screen management libraries an explanation of
+ this approach is given here. This approach has been motivated by
+ experience with programs that require some sort of screen management.
+
+ Most programs that use SLsmg are composed of specific textual objects
+ or objects made up of line drawing characters. For example, consider
+ an application with a menu bar with drop down menus. The menus might
+ be enclosed by some sort of frame or perhaps a shadow. The basic idea
+ is to associate an integer to each of the objects (e.g., menu bar,
+ shadow, current menu item, etc.) and create a mapping from the integer
+ to the set of attributes. In the terminology of SLsmg, the integer is
+ simply called an object.
+
+ For example, the menu bar might be associated with the object 1, the
+ drop down menu could be object 2, the shadow could be object 3, and so
+ on.
+
+ The range of values for the object integer is restricted from 0 up to
+ and including 255 on all systems except MSDOS where the maximum
+ allowed integer is 15 (-- This difference is due to memory constraints
+ imposed by MSDOS. This restriction might be removed in a future
+ version of the library.--) . The object numbered zero should not be
+ regarding as an object at all. Rather it should be regarded as all
+ other objects that have not explicitly been given an object number.
+ SLsmg, or more precisely SLtt, refers to the attributes of this
+ special object as the default or normal attributes.
+
+ The SLsmg routines know nothing about the mapping of the color to the
+ attributes associated with the color. The actual mapping takes place
+ at a lower level in the SLtt routines. Hence, to map an object to the
+ actual set of attributes requires a call to any of the following SLtt
+ routines:
+
+
+ void SLtt_set_color (int obj, char *name, char *fg, char *bg);
+ void SLtt_set_color_object (int obj, SLtt_Char_Type attr);
+ void SLtt_set_mono (int obj, char *, SLtt_Char_Type attr);
+
+
+
+ Only the first of these routines will be discussed briefly here. The
+ latter two functions allow more fine control over the object to
+ attribute mapping (such as assigning a ``blink'' attribute to the
+ object). For a more full explanation on all of these routines see the
+ section about the SLtt interface.
+
+ The SLtt_set_color function takes four parameters. The first
+ parameter, obj, is simply the integer of the object for which
+ attributes are to be assigned. The second parameter is currently
+ unused by these routines. The third and forth parameters, fg and bg,
+ are the names of the foreground and background color to be used
+ associated with the object. The strings that one can use for the
+ third and fourth parameters can be any one of the 16 colors:
+
+
+ "black" "gray"
+ "red" "brightred"
+ "green" "brightgreen"
+ "brown" "yellow"
+ "blue" "brightblue"
+ "magenta" "brightmagenta"
+ "cyan" "brightcyan"
+ "lightgray" "white"
+
+
+
+ The value of the foreground parameter fg can be anyone of these six-
+ teen colors. However, on most terminals, the background color will
+ can only be one of the colors listed in the first column (-- This is
+ also true on the Linux console. However, it need not be the case and
+ hopefully the designers of Linux will someday remove this restric-
+ tion.--) .
+
+ Of course not all terminals are color terminals. If the S-Lang global
+ variable SLtt_Use_Ansi_Colors is non-zero, the terminal is assumed to
+ be a color terminal. The SLtt_get_terminfo will try to determine
+ whether or not the terminal supports colors and set this variable
+ accordingly. It does this by looking for the capability in the
+ terminfo/termcap database. Unfortunately many Unix databases lack
+ this information and so the SLtt_get_terminfo routine will check
+ whether or not the environment variable COLORTERM exists. If it
+ exists, the terminal will be assumed to support ANSI colors and
+ SLtt_Use_Ansi_Colors will be set to one. Nevertheless, the
+ application should provide some other mechanism to set this variable,
+ e.g., via a command line parameter.
+
+ When the SLtt_Use_Ansi_Colors variable is zero, all objects with
+ numbers greater than one will be displayed in inverse video (-- This
+ behavior can be modified by using the SLtt_set_mono function call.--)
+ .
+
+ With this background, the SLsmg functions for setting the character
+ attributes can now be defined. These functions simply set the object
+ attributes that are to be assigned to subsequent characters written to
+ the virtual display. For this reason, the new attribute is called the
+ current attribute.
+
+ void SLsmg_set_color (int obj); Set the current attribute to those of
+ object obj.
+
+ void SLsmg_normal_video (void); This function is equivalent to
+ SLsmg_set_color (0).
+
+ void SLsmg_reverse_video (void); This function is equivalent to
+ SLsmg_set_color (1). On monochrome terminals, it is equivalent to
+ setting the subsequent character attributes to inverse video.
+
+ Unfortunately there does not seem to be a standard way for the
+ application or, in particular, the library to determine which color
+ will be used by the terminal for the default background. Such
+ information would be useful in initializing the foreground and
+ background colors associated with the default color object (0). FOr
+ this reason, it is up to the application to provide some means for the
+ user to indicate what these colors are for the particular terminal
+ setup. To facilitate this, the SLtt_get_terminfo function checks for
+ the existence of the COLORFGBG environment variable. If this variable
+ exists, its value will be used to initialize the colors associated
+ with the default color object. Specifically, the value is assumed to
+ consist of a foreground color name and a background color name
+ separated by a semicolon. For example, if the value of COLORTERM is
+ lightgray;blue, the default color object will be initialized to
+ represent a lightgray foreground upon a blue background.
+
+
+ 5.4.5. Lines and Alternate Character Sets
+
+ The S-Lang screen management library also includes routines for
+ turning on and turning off alternate character sets. This is
+ especially useful for drawing horizontal and vertical lines.
+
+ void SLsmg_set_char_set (int flag); If flag is non-zero, subsequent
+ write functions will use characters from the alternate character set.
+ If flag is zero, the default, or, ordinary character set will be used.
+
+ void SLsmg_draw_hline (int len); Draw a horizontal line from the
+ current position to the column that is len characters to the right.
+
+ void SLsmg_draw_vline (int len); Draw a horizontal line from the
+ current position to the row that is len rows below.
+
+ void SLsmg_draw_box (int r, int c, int dr, int dc); Draw a box whose
+ upper right corner is at row r and column c. The box spans dr rows
+ and dc columns. The current position will be left at row r and column
+ c.
+
+
+ 5.4.6. Miscellaneous Functions
+
+
+ void SLsmg_touch_lines (int r, int n); Mark screen rows numbered r, r
+ + 1, ... r + (n - 1) as modified. When SLsmg_refresh is called, these
+ rows will be completely redrawn.
+ unsigned short SLsmg_char_at(void); Returns the character and its
+ attributes object number at the current cursor position. The
+ character itself occupies the lower byte and the object attributes
+ number forms the upper byte. The object returned by this function
+ call should not be written back out via any of the functions that
+ write characters or character strings.
+
+
+
+ 5.5. Variables
+
+
+
+ The following S-Lang global variables are used by the SLsmg interface.
+ Some of these have been previously discussed.
+
+ int SLtt_Screen_Rows; int SLtt_Screen_Cols; The number of rows and
+ columns of the physical display. If either of these numbers changes,
+ the functions SLsmg_reset_smg and SLsmg_init_smg should be called
+ again so that the SLsmg routines can re-adjust to the new size.
+
+ int SLsmg_Tab_Width; Set this variable to the tab width that will be
+ used when expanding tab characters. The default is 8.
+
+ int SLsmg_Display_Eight_Bit This variable determines how characters
+ with the high bit set are to be output. Specifically, a character
+ with the high bit set with a value greater than or equal to this value
+ is output as is; otherwise, it will be output in a 7-bit
+ representation. The default value for this variable is 128 for MSDOS
+ and 160 for other systems (ISO-Latin).
+
+ int SLtt_Use_Ansi_Colors; If this value is non-zero, the terminal is
+ assumed to support ANSI colors otherwise it is assumed to be
+ monochrome. The default is 0.
+
+ int SLtt_Term_Cannot_Scroll; If this value is zero, the SLsmg will
+ attempt to scroll the physical display to optimize the update. If it
+ is non-zero, the screen management routines will not perform this
+ optimization. For some applications, this variable should be set to
+ zero. The default value is set by the SLtt_get_terminfo function.
+
+
+
+ 5.6. Hints for using SLsmg
+
+
+ This section discusses some general design issues that one must face
+ when writing an application that requires some sort of screen
+ management.
+
+
+
+ 6. Signal Functions
+
+
+
+ Almost all non-trivial programs must worry about signals. This is
+ especially true for programs that use the S-Lang terminal input/output
+ and screen management routines. Unfortunately, there is no fixed way
+ to handle signals; otherwise, the Unix kernel would take care of all
+ issues regarding signals and the application programmer would never
+ have to worry about them. For this reason, none of the routines in
+ the S-Lang library catch signals; however, some of the routines block
+ the delivery of signals during crucial moments. It is up to the
+ application programmer to install handlers for the various signals of
+ interest.
+
+ For the interpreter, the most important signal to worry about is
+ SIGINT. This signal is usually generated when the user presses Ctrl-C
+ at the keyboard. The interpreter checks the value of the SLang_Error
+ variable to determine whether or not it should abort the interpreting
+ process and return control back to the application. This means that
+ if SIGINT is to be used to abort the interpreter, a signal handler for
+ SIGINT should be installed. The handler should set the value of
+ SLang_Error to SL_USER_BREAK.
+
+ Applications that use the tty getkey routines or the screen management
+ routines must worry about signals such as:
+
+
+ SIGINT interrupt
+ SIGTSTP stop
+ SIGQUIT quit
+ SIGTTOU background write
+ SIGTTIN background read
+ SIGWINCH window resize
+
+
+
+ It is important that handlers be established for these signals while
+ the either the SLsmg routines or the getkey routines are initialized.
+ The SLang_init_tty, SLang_reset_tty, SLsmg_init_smg, and
+ SLsmg_reset_smg functions block these signals from occuring while they
+ are being called.
+
+ Since a signal can be delivered at any time, it is important for the
+ signal handler to call only functions that can be called from a signal
+ handler. This usually means that such function must be re-entrant. In
+ particular, the SLsmg routines are not re-entrant; hence, they should
+ not be called when a signal is being processed unless the application
+ can ensure that the signal was not delivered while an SLsmg function
+ was called. This statement applies to many other functions such as
+ malloc, or, more generally, any function that calls malloc. The
+ upshot is that the signal handler should not attempt to do too much
+ except set a global variable for the application to look at while not
+ in a signal handler.
+
+ The S-Lang library provides two functions for blocking and unblocking
+ the above signals:
+
+
+ int SLsig_block_signals (void);
+ int SLsig_unblock_signals (void);
+
+
+
+ It should be noted that for every call to SLsig_block_signals, a cor-
+ responding call should be made to SLsig_unblock_signals, e.g.,
+
+
+ void update_screen ()
+ {
+ SLsig_block_signals ();
+
+ /* Call SLsmg functions */
+ .
+ .
+ SLsig_unblock_signals ();
+ }
+
+
+
+ See demo/pager.c for examples.
+
+
+
+ 7. Searching Functions
+
+
+
+ The S-Lang library incorporates two types of searches: Regular
+ expression pattern matching and ordinary searching.
+
+
+ 7.1. Regular Expressions
+
+
+
+ !!! No documentation available yet !!!
+
+
+
+ 7.2. Simple Searches
+
+
+ The routines for ordinary searching are defined in the slsearch.c
+ file. To use these routines, simply include "slang.h" in your program
+ and simply call the appropriate routines.
+
+ The searches can go in either a forward or backward direction and can
+ either be case or case insensitive. The region that is searched may
+ contain null characters (ASCII 0) however, the search string cannot in
+ the current implementation. In addition the length of the string to
+ be found is currently limited to 256 characters.
+
+ Before searching, the function SLsearch_init must first be called to
+ `preprocess' the search string.
+
+
+
+ 7.3. Initialization
+
+
+ The function SLsearch_init must be called before a search can take
+ place. Its prototype is:
+
+
+ int SLsearch_init (char *key, int dir, int case_sens, SLsearch_Type *st);
+
+
+
+ Here key is the string to be searched for. dir specifies the direc-
+ tion of the search: a value greater than zero is used for searching
+ forward and a value less than zero is used for searching backward.
+ The parameter case_sens specifies whether the search is case sensitive
+ or not. A non-zero value indicates that case is important. st is a
+ pointer to a structure of type SLsearch_Type defined in "slang.h".
+ This structure is initialized by this routine and must be passed to
+ SLsearch when the search is actually performed.
+
+ This routine returns the length of the string to be searched for.
+
+
+
+ 7.4. SLsearch
+
+
+
+ Prototype: unsigned char *SLsearch (unsigned char *pmin,
+ unsigned char *pmax,
+ SLsearch_Type *st);
+
+
+
+ This function performs the search defined by a previous call to
+ SLsearch_init over a region specified by the pointers pmin and pmax.
+
+ It returns a pointer to the start of the match if successful or it
+ will return NULL if a match was not found.
+
+
+
+ A. Copyright
+
+ The S-Lang library is distributed under two copyrights: the GNU Genral
+ Public License, and the Artistic License. Any program that uses the
+ interpreter must adhere to rules of one of these licenses.
+
+
+ A.1. The GNU Public License
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+
+
+ The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License
+ is intended to guarantee your freedom to share and change free soft-
+ ware--to make sure the software is free for all its users. This Gen-
+ eral Public License applies to most of the Free Software Foundation's
+ software and to any other program whose authors commit to using it.
+ (Some other Free Software Foundation software is covered by the GNU
+ Library General Public License instead.) You can apply it to your
+ programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it
+ in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if
+ you distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+ (2) offer you this license which gives you legal permission to copy,
+ distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on,
+ we want its recipients to know that what they have is not the
+ original, so that any problems introduced by others will not reflect
+ on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at
+ all.
+
+ The precise terms and conditions for copying, distribution and
+ modification follow.
+
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+
+
+ 0. This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The "Program", below,
+ refers to any such program or work, and a "work based on the Program"
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term "modification".) Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of
+ running the Program is not restricted, and the output from the Program
+ is covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether
+ that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.
+
+ You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a
+ fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above,
+ provided that you also meet all of these conditions:
+
+
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+
+
+ These requirements apply to the modified work as a whole. If identi-
+ fiable sections of that work are not derived from the Program, and can
+ be reasonably considered independent and separate works in themselves,
+ then this License, and its terms, do not apply to those sections when
+ you distribute them as separate works. But when you distribute the
+ same sections as part of a whole which is a work based on the Program,
+ the distribution of the whole must be on the terms of this License,
+ whose permissions for other licensees extend to the entire whole, and
+ thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program
+ with the Program (or with a work based on the Program) on a volume of
+ a storage or distribution medium does not bring the other work under
+ the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+
+
+ The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to con-
+ trol compilation and installation of the executable. However, as a
+ special exception, the source code distributed need not include any-
+ thing that is normally distributed (in either source or binary form)
+ with the major components (compiler, kernel, and so on) of the operat-
+ ing system on which the executable runs, unless that component itself
+ accompanies the executable.
+
+ If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent
+ access to copy the source code from the same place counts as
+ distribution of the source code, even though third parties are not
+ compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense or distribute the Program is
+ void, and will automatically terminate your rights under this License.
+ However, parties who have received copies, or rights, from you under
+ this License will not have their licenses terminated so long as such
+ parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying
+ the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further
+ restrictions on the recipients' exercise of the rights granted herein.
+ You are not responsible for enforcing compliance by third parties to
+ this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent
+ license would not permit royalty-free redistribution of the Program by
+ all those who receive copies directly or indirectly through you, then
+ the only way you could satisfy both it and this License would be to
+ refrain entirely from distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made
+ generous contributions to the wide range of software distributed
+ through that system in reliance on consistent application of that
+ system; it is up to the author/donor to decide if he or she is willing
+ to distribute software through any other system and a licensee cannot
+ impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License
+ may add an explicit geographical distribution limitation excluding
+ those countries, so that distribution is permitted only in or among
+ countries not thus excluded. In such case, this License incorporates
+ the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new
+ versions of the General Public License from time to time. Such new
+ versions will be similar in spirit to the present version, but may
+ differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and
+ "any later version", you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a
+ version number of this License, you may choose any version ever
+ published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by
+ the Free Software Foundation, write to the Free Software Foundation;
+ we sometimes make exceptions for this. Our decision will be guided by
+ the two goals of preserving the free status of all derivatives of our
+ free software and of promoting the sharing and reuse of software
+ generally.
+
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+ REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+ possible use to the public, the best way to achieve this is to make it
+ free software which everyone can redistribute and change under these
+ terms.
+
+ To do so, attach the following notices to the program. It is safest
+ to attach them to the start of each source file to most effectively
+ convey the exclusion of warranty; and each file should have at least
+ the "copyright" line and a pointer to where the full notice is found.
+
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+
+ Also add information on how to contact you by electronic and paper
+ mail.
+
+ If the program is interactive, make it output a short notice like this
+ when it starts in an interactive mode:
+
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+
+
+ The hypothetical commands `show w' and `show c' should show the appro-
+ priate parts of the General Public License. Of course, the commands
+ you use may be called something other than `show w' and `show c'; they
+ could even be mouse-clicks or menu items--whatever suits your program.
+
+ You should also get your employer (if you work as a programmer) or
+ your school, if any, to sign a "copyright disclaimer" for the program,
+ if necessary. Here is a sample; alter the names:
+
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+
+
+ This General Public License does not permit incorporating your program
+ into proprietary programs. If your program is a subroutine library,
+ you may consider it more useful to permit linking proprietary applica-
+ tions with the library. If this is what you want to do, use the GNU
+ Library General Public License instead of this License.
+
+
+ A.2. The Artistic License
+
+
+
+ The "Artistic License"
+
+ Preamble
+
+
+
+ The intent of this document is to state the conditions under which a
+ Package may be copied, such that the Copyright Holder maintains some
+ semblance of artistic control over the development of the package,
+ while giving the users of the package the right to use and distribute
+ the Package in a more-or-less customary fashion, plus the right to
+ make reasonable modifications.
+
+ Definitions:
+
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+
+
+ 1. You may make and give away verbatim copies of the source form of
+ the Standard Version of this Package without restriction, provided
+ that you duplicate all of the original copyright notices and associ-
+ ated disclaimers.
+
+ 2. You may apply bug fixes, portability fixes and other modifications
+ derived from the Public Domain or from the Copyright Holder. A
+ Package modified in such a way shall still be considered the Standard
+ Version.
+
+ 3. You may otherwise modify your copy of this Package in any way,
+ provided that you insert a prominent notice in each changed file
+ stating how and when you changed that file, and provided that you do
+ at least ONE of the following:
+
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+
+
+ 4. You may distribute the programs of this Package in object code or
+ executable form, provided that you do at least ONE of the following:
+
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+
+
+ 5. You may charge a reasonable copying fee for any distribution of
+ this Package. You may charge any fee you choose for support of this
+ Package. You may not charge a fee for this Package itself. However,
+ you may distribute this Package in aggregate with other (possibly com-
+ mercial) programs as part of a larger (possibly commercial) software
+ distribution provided that you do not advertise this Package as a
+ product of your own. You may embed this Package's interpreter within
+ an executable of yours (by linking); this shall be construed as a mere
+ form of aggregation, provided that the complete Standard Version of
+ the interpreter is so embedded.
+
+ 6. The scripts and library files supplied as input to or produced as
+ output from the programs of this Package do not automatically fall
+ under the copyright of this Package, but belong to whomever generated
+ them, and may be sold commercially, and may be aggregated with this
+ Package. If such scripts or library files are aggregated with this
+ Package via the so-called "undump" or "unexec" methods of producing a
+ binary executable image, then distribution of such an image shall
+ neither be construed as a distribution of this Package nor shall it
+ fall under the restrictions of Paragraphs 3 and 4, provided that you
+ do not represent such an executable image as a Standard Version of
+ this Package.
+ 7. C subroutines (or comparably compiled subroutines in other
+ languages) supplied by you and linked into this Package in order to
+ emulate subroutines and variables of the language defined by this
+ Package shall not be considered part of this Package, but are the
+ equivalent of input as in Paragraph 6, provided these subroutines do
+ not change the language in any way that would cause it to fail the
+ regression tests for the language.
+
+ 8. Aggregation of this Package with a commercial distribution is
+ always permitted provided that the use of this Package is embedded;
+ that is, when no overt attempt is made to make this Package's
+ interfaces visible to the end user of the commercial distribution.
+ Such use shall not be construed as a distribution of this Package.
+
+ 9. The name of the Copyright Holder may not be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+ 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+ Table of Contents
+
+
+ 1. Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
+ 1.1. A Brief History of S-Lang . . . . . . . . . . . . . . . . . . 2
+ 1.2. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 2
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 3. Interpreter Interface . . . . . . . . . . . . . . . . . . . . . 5
+ 3.1. Embedding the Interpreter . . . . . . . . . . . . . . . . . . 5
+ 3.2. Calling the Interpreter . . . . . . . . . . . . . . . . . . . 6
+ 3.2.1. Loading Files . . . . . . . . . . . . . . . . . . . . . . . 6
+ 3.2.2. Loading Strings . . . . . . . . . . . . . . . . . . . . . . 7
+ 3.3. Intrinsic Functions . . . . . . . . . . . . . . . . . . . . . 7
+ 3.3.1. Restrictions on Intrinsic Functions . . . . . . . . . . . . 8
+ 3.3.2. Adding a New Intrinsic . . . . . . . . . . . . . . . . . . 9
+ 3.3.3. More Complicated Intrinsics . . . . . . . . . . . . . . . . 11
+ 3.4. Intrinsic Variables . . . . . . . . . . . . . . . . . . . . . 13
+ 3.5. Aggregate Data Objects . . . . . . . . . . . . . . . . . . . 15
+ 3.5.1. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . 16
+ 3.5.2. Structures . . . . . . . . . . . . . . . . . . . . . . . . 18
+ 3.5.2.1. Interpreter Structures . . . . . . . . . . . . . . . . . 18
+ 3.5.2.2. Intrinsic Structures . . . . . . . . . . . . . . . . . . 22
+ 4. Keyboard Interface . . . . . . . . . . . . . . . . . . . . . . 24
+ 4.1. Initializing the Keyboard Interface . . . . . . . . . . . . . 24
+ 4.2. Resetting the Keyboard Interface . . . . . . . . . . . . . . 25
+ 4.3. Initializing the SLkp Routines . . . . . . . . . . . . . . . 25
+ 4.4. Setting the Interrupt Handler . . . . . . . . . . . . . . . . 26
+ 4.5. Reading Keyboard Input with SLang_getkey . . . . . . . . . . 27
+ 4.6. Reading Keyboard Input with SLkp_getkey . . . . . . . . . . . 28
+ 4.7. Buffering Input . . . . . . . . . . . . . . . . . . . . . . . 29
+ 4.8. Global Variables . . . . . . . . . . . . . . . . . . . . . . 30
+ 5. Screen Management . . . . . . . . . . . . . . . . . . . . . . . 31
+ 5.1. Initialization . . . . . . . . . . . . . . . . . . . . . . . 31
+ 5.2. Resetting SLsmg . . . . . . . . . . . . . . . . . . . . . . . 31
+ 5.3. Handling Screen Resize Events . . . . . . . . . . . . . . . . 32
+ 5.4. SLsmg Functions . . . . . . . . . . . . . . . . . . . . . . . 33
+ 5.4.1. Positioning the cursor . . . . . . . . . . . . . . . . . . 33
+ 5.4.2. Writing to the Display . . . . . . . . . . . . . . . . . . 34
+ 5.4.3. Erasing the Display . . . . . . . . . . . . . . . . . . . . 35
+ 5.4.4. Setting Character Attributes . . . . . . . . . . . . . . . 35
+ 5.4.5. Lines and Alternate Character Sets . . . . . . . . . . . . 37
+ 5.4.6. Miscellaneous Functions . . . . . . . . . . . . . . . . . . 37
+ 5.5. Variables . . . . . . . . . . . . . . . . . . . . . . . . . . 38
+ 5.6. Hints for using SLsmg . . . . . . . . . . . . . . . . . . . . 38
+ 6. Signal Functions . . . . . . . . . . . . . . . . . . . . . . . 39
+ 7. Searching Functions . . . . . . . . . . . . . . . . . . . . . . 41
+ 7.1. Regular Expressions . . . . . . . . . . . . . . . . . . . . . 41
+ 7.2. Simple Searches . . . . . . . . . . . . . . . . . . . . . . . 41
+ 7.3. Initialization . . . . . . . . . . . . . . . . . . . . . . . 41
+ 7.4. SLsearch . . . . . . . . . . . . . . . . . . . . . . . . . . 41
+ A. Copyright . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
+ A.1. The GNU Public License . . . . . . . . . . . . . . . . . . . 43
+ A.2. The Artistic License . . . . . . . . . . . . . . . . . . . . 49
+
+
+
diff --git a/libslang/doc/text/slang.txt b/libslang/doc/text/slang.txt
new file mode 100644
index 0000000..6867293
--- /dev/null
+++ b/libslang/doc/text/slang.txt
@@ -0,0 +1,5642 @@
+ A Guide to the S-Lang Language
+ John E. Davis, davis@space.mit.edu
+ Mar 23, 2003
+ ____________________________________________________________
+
+ Table of Contents
+
+
+
+ Preface
+
+ 1. A Brief History of S-Lang
+ 2. Acknowledgements
+ 2. Introduction
+ 3. Language Features
+ 4. Data Types and Operators
+ 5. Statements and Functions
+ 6. Error Handling
+ 7. Run-Time Library
+ 8. Input/Output
+ 9. Obtaining S-Lang
+ 9. Overview of the Language
+ 10. Variables and Functions
+ 11. Strings
+ 12. Referencing and Dereferencing
+ 13. Arrays
+ 14. Structures and User-Defined Types
+ 15. Namespaces
+ 15. Data Types and Literal Constants
+ 16. Predefined Data Types
+ 16.1 Integers
+ 16.2 Floating Point Numbers
+ 16.3 Complex Numbers
+ 16.4 Strings
+ 16.5 Null_Type
+ 16.6 Ref_Type
+ 16.7 Array_Type and Struct_Type
+ 16.8 DataType_Type Type
+
+ 17. Typecasting: Converting from one Type to Another
+
+ 17. Identifiers
+
+ 17. Variables
+
+ 17. Operators
+ 18. Unary Operators
+ 19. Binary Operators
+ 19.1 Arithmetic Operators
+ 19.2 Relational Operators
+ 19.3 Boolean Operators
+ 19.4 Bitwise Operators
+ 19.5 Namespace operator
+ 19.6 Operator Precedence
+ 19.7 Binary Operators and Functions Returning Multiple Values
+
+ 20. Mixing Integer and Floating Point Arithmetic
+ 21. Short Circuit Boolean Evaluation
+ 21. Statements
+ 22. Variable Declaration Statements
+ 23. Assignment Statements
+ 24. Conditional and Looping Statements
+ 24.1 Conditional Forms
+ 24.1.1 if
+ 24.1.2 if-else
+ 24.1.3 !if
+ 24.1.4 orelse, andelse
+ 24.1.5 switch
+ 24.2 Looping Forms
+ 24.2.1 while
+ 24.2.2 do...while
+ 24.2.3 for
+ 24.2.4 loop
+ 24.2.5 for
+ 24.2.6 forever
+ 24.2.7 foreach
+
+ 25. break, return, continue
+
+ 25. Functions
+ 26. Declaring Functions
+ 27. Parameter Passing Mechanism
+ 28. Referencing Variables
+ 29. Functions with a Variable Number of Arguments
+ 30. Returning Values
+ 31. Multiple Assignment Statement
+ 32. Exit-Blocks
+ 32. Name Spaces
+ 32. Arrays
+ 33. Creating Arrays
+ 33.1 Range Arrays
+ 33.2 Creating arrays via the dereference operator
+
+ 34. Reshaping Arrays
+ 35. Indexing Arrays
+ 36. Arrays and Variables
+ 37. Using Arrays in Computations
+ 37. Associative Arrays
+ 37. Structures and User-Defined Types
+ 38. Defining a Structure
+ 39. Accessing the Fields of a Structure
+ 40. Linked Lists
+ 41. Defining New Types
+ 41. Error Handling
+ 42. Error-Blocks
+ 43. Clearing Errors
+ 43. Loading Files: evalfile and autoload
+ 43. File Input/Output
+ 44. Input/Output via stdio
+ 44.1 Stdio Overview
+ 44.2 Stdio Examples
+
+ 45. POSIX I/O
+ 46. Advanced I/O techniques
+ 46.1 Example: Reading /var/log/wtmp
+ 46.1 Debugging
+ 46.1 Regular Expressions
+
+ 47. S-Lang RE Syntax
+ 48. Differences between S-Lang and egrep REs
+ 48. Future Directions
+ 48. Copyright
+ A. The GNU Public License
+ B. The Artistic License
+
+
+ ______________________________________________________________________
+
+
+
+ 1. Preface
+
+
+
+ S-Lang is an interpreted language that was designed from the start to
+ be easily embedded into a program to provide it with a powerful
+ extension language. Examples of programs that use S-Lang as an
+ extension language include the jed text editor, the slrn newsreader,
+ and sldxe (unreleased), a numerical computation program. For this
+ reason, S-Lang does not exist as a separate application and many of
+ the examples in this document are presented in the context of one of
+ the above applications.
+
+ S-Lang is also a programmer's library that permits a programmer to
+ develop sophisticated platform-independent software. In addition to
+ providing the S-Lang extension language, the library provides
+ facilities for screen management, keymaps, low-level terminal I/O,
+ etc. However, this document is concerned only with the extension
+ language and does not address these other features of the S-Lang
+ library. For information about the other components of the library,
+ the reader is referred to the The S-Lang Library Reference.
+
+
+ 1.1. A Brief History of S-Lang
+
+
+
+ I first began working on S-Lang sometime during the fall of 1992. At
+ that time I was writing a text editor (jed), which I wanted to endow
+ with a macro language. It occured to me that an application-
+ independent language that could be embedded into the editor would
+ prove more useful because I could envision embedding it into other
+ programs. As a result, S-Lang was born.
+
+ S-Lang was originally a stack language that supported a postscript-
+ like syntax. For that reason, I named it S-Lang, where the S was
+ supposed to emphasize its stack-based nature. About a year later, I
+ began to work on a preparser that would allow one to write using a
+ more traditional infix syntax making it easier to use for those
+ unfamiliar with stack based languages. Currently, the syntax of the
+ language resembles C, nevertheless some postscript-like features still
+ remain, e.g., the `%' character is still used as a comment delimiter.
+
+
+
+ 1.2. Acknowledgements
+
+
+
+ Since I first released S-Lang, I have received a lot feedback about
+ the library and the language from many people. This has given me the
+ opportunity and pleasure to interact with several people to make the
+ library portable and easy to use. In particular, I would like to
+ thank the following individuals:
+
+ Luchesar Ionkov <lionkov@sf.cit.bg> for his comments and criticisms of
+ the syntax of the language. He was the person who made me realize
+ that the low-level byte-code engine should be totally type-
+ independent. He also improved the tokenizer and preparser and
+ impressed upon me that the language needed a grammar.
+
+ Mark Olesen <olesen@weber.me.queensu.ca> for his many patches to
+ various aspects of the library and his support on AIX. He also
+ contributed a lot to the pre-processing (SLprep) routines.
+
+ John Burnell <j.burnell@irl.cri.nz> for the OS/2 port of the video and
+ keyboard routines. He also made value suggestions regarding the
+ interpreter interface.
+
+ Darrel Hankerson <hankedr@mail.auburn.edu> for cleaning up and
+ unifying some of the code and the makefiles.
+
+ Dominik Wujastyk <ucgadkw@ucl.ac.uk> who was always willing to test
+ new releases of the library.
+
+ Michael Elkins <me@muddcs.cs.hmc.edu> for his work on the curses
+ emulation.
+
+ Ulli Horlacher <framstag@belwue.de> and Oezguer Kesim <kesim@math.fu-
+ berlin.de> for the S-Lang newsgroup and mailing list.
+
+ Hunter Goatley, Andy Harper <Andy.Harper@kcl.ac.uk>, and Martin P.J.
+ Zinser <zinser@decus.decus.de> for their VMS support.
+
+ Dave Sims <sims@usa.acsys.com> and Chin Huang <cthuang@vex.net> for
+ Windows 95 and Windows NT support.
+
+ Lloyd Zusman <ljz@asfast.com> and Rich Roth <rich@on-the-net.com> for
+ creating and maintaining www.s-lang.org.
+
+ I am also grateful to many other people who send in bug-reports and
+ bug-fixes, for without such community involvement, S-Lang would not be
+ as well-tested and stable as it is. Finally, I would like to thank my
+ wife for her support and understanding while I spent long weekend
+ hours developing the library.
+
+
+
+ 2. Introduction
+
+
+
+ S-Lang is a powerful interpreted language that may be embedded into an
+ application to make the application extensible. This enables the
+ application to be used in ways not envisioned by the programmer, thus
+ providing the application with much more flexibility and power.
+ Examples of applications that take advantage of the interpreter in
+ this way include the jed editor and the slrn newsreader.
+
+
+ 2.1. Language Features
+
+
+ The language features both global and local variables, branching and
+ looping constructs, user-defined functions, structures, datatypes, and
+ arrays. In addition, there is limited support for pointer types. The
+ concise array syntax rivals that of commercial array-based numerical
+ computing environments.
+
+
+ 2.2. Data Types and Operators
+
+
+
+ The language provides built-in support for string, integer (signed and
+ unsigned long and short), double precision floating point, and double
+ precision complex numbers. In addition, it supports user defined
+ structure types, multi-dimensional array types, and associative
+ arrays. To facilitate the construction of sophisticated data
+ structures such as linked lists and trees, a `reference' type was
+ added to the language. The reference type provides much of the same
+ flexibility as pointers in other languages. Finally, applications
+ embedding the interpreter may also provide special application
+ specific types, such as the Mark_Type that the jed editor provides.
+
+ The language provides standard arithmetic operations such as addition,
+ subtraction, multiplication, and division. It also provides support
+ for modulo arithmetic as well as operations at the bit level, e.g.,
+ exclusive-or. Any binary or unary operator may be extended to work
+ with any data type. For example, the addition operator (+) has been
+ extended to work between string types to permit string concatenation.
+
+ The binary and unary operators work transparently with array types.
+ For example, if a and b are arrays, then a + b produces an array whose
+ elements are the result of element by element addition of a and b.
+ This permits one to do vector operations without explicitly looping
+ over the array indices.
+
+
+
+ 2.3. Statements and Functions
+
+
+
+ The S-Lang language supports several types of looping constructs and
+ conditional statements. The looping constructs include while,
+ do...while, for, forever, loop, foreach, and _for. The conditional
+ statements include if, if-then-else, and !if.
+
+ User defined functions may be defined to return zero, one, or more
+ values. Functions that return zero values are similar to `procedures'
+ in languages such as PASCAL. The local variables of a function are
+ always created on a stack allowing one to create recursive functions.
+ Parameters to a function are always passed by value and never by
+ reference. However, the language supports a reference data type that
+ allows one to simulate pass by reference.
+
+ Unlike many interpreted languages, S-Lang allows functions to be
+ dynamically loaded (function autoloading). It also provides
+ constructs specifically designed for error handling and recovery as
+ well as debugging aids (e.g., function tracebacks).
+
+ Functions and variables may be declared as private belonging to a
+ namespace associated with the compilation unit that defines the
+ function or variable. The ideas behind the namespace implementation
+ stems from the C language and should be quite familiar to any one
+ familiar with C.
+
+
+
+ 2.4. Error Handling
+
+
+
+ The S-Lang language defines a construct called an error-block that may
+ be used for error handling and recovery. When a non-fatal run-time
+ error is encountered, any error blocks that have been defined are
+ executed as the run-time stack unwinds. An error block can optionally
+ clear the error and the program will continue running after the
+ statement that triggered the error. This mechanism is somewhat
+ similar to try-catch in C++.
+
+
+
+ 2.5. Run-Time Library
+
+
+
+ Functions that compose the S-Lang run-time library are called
+ intrinsics. Examples of S-Lang intrinsic functions available to every
+ S-Lang application include string manipulation functions such as
+ strcat, strchop, and strcmp. The S-Lang library also provides
+ mathematical functions such as sin, cos, and tan; however, not all
+ applications enable the use of these intrinsics. For example, to
+ conserve memory, the 16 bit version of the jed editor does not provide
+ support for any mathematics other than simple integer arithmetic,
+ whereas other versions of the editor do support these functions.
+
+ Most applications embedding the languages will also provide a set of
+ application specific intrinsic functions. For example, the jed editor
+ adds over 100 application specific intrinsic functions to the
+ language. Consult your application specific documentation to see what
+ additional intrinsics are supported.
+
+
+
+ 2.6. Input/Output
+
+
+ The language supports C-like stdio input/output functions such as
+ fopen, fgets, fputs, and fclose. In addition it provides two
+ functions, message and error, for writing to the standard output
+ device and standard error. Specific applications may provide other
+ I/O mechanisms, e.g., the jed editor supports I/O to files via the
+ editor's buffers.
+
+ 2.7. Obtaining S-Lang
+
+
+
+ Comprehensive information about the library may be obtained via the
+ World Wide Web from http://www.s-lang.org.
+
+ S-Lang as well as some programs that embed it are freely available via
+ anonymous ftp in the United States from
+
+ o ftp://space.mit.edu/pub/davis.
+
+ It is also available outside the United States from the following
+ mirror sites:
+
+ o ftp://ftp.uni-stuttgart.de/pub/unix/misc/slang/
+
+ o ftp://ftp.fu-berlin.de/pub/unix/news/slrn/
+
+ o ftp://ftp.ntua.gr/pub/lang/slang/
+
+ The Usenet newsgroup alt.lang.s-lang was created for S-Lang
+ programmers to exchange information and share macros for the various
+ programs the embed the language. The newsgroup comp.editors can be a
+ useful resource for S-Lang macros for the jed editor. Similarly, slrn
+ users will find news.software.readers to be a valuable source of
+ information.
+
+ Finally, two mailing lists dealing with the S-Lang library have been
+ created:
+
+ o slang-announce@babayaga.math.fu-berlin.de
+
+ o slang-workers@babayaga.math.fu-berlin.de
+
+ The first list is for announcements of new releases of the library,
+ while the second list is intended for those who use the library for
+ their own code development. To subscribe to the announcement list,
+ send an email to slang-announce-subscribe@babayaga.math.fu-
+ berlin.de and include the word subscribe in the body of the
+ message. To subscribe to the developers list, use the address
+ slang-workers-subscribe@babayaga.math.fu-berlin.de.
+
+
+
+ 3. Overview of the Language
+
+
+
+ This purpose of this section is to give the reader a feel for the S-
+ Lang language, its syntax, and its capabilities. The information and
+ examples presented in this section should be sufficient to provide the
+ reader with the necessary background to understand the rest of the
+ document.
+
+
+ 3.1. Variables and Functions
+
+
+
+ S-Lang is different from many other interpreted languages in the sense
+ that all variables and functions must be declared before they can be
+ used.
+
+ Variables are declared using the variable keyword, e.g.,
+
+
+ variable x, y, z;
+
+
+
+ declares three variables, x, y, and z. Note the semicolon at the end
+ of the statement. All S-Lang statements must end in a semi-colon.
+
+ Unlike compiled languages such as C, it is not necessary to specify
+ the data type of a S-Lang variable. The data type of a S-Lang
+ variable is determined upon assignment. For example, after execution
+ of the statements
+
+
+ x = 3;
+ y = sin (5.6);
+ z = "I think, therefore I am.";
+
+
+
+ x will be an integer, y will be a double, and z will be a string. In
+ fact, it is even possible to re-assign x to a string:
+
+
+ x = "x was an integer, but now is a string";
+
+
+
+ Finally, one can combine variable declarations and assignments in the
+ same statement:
+
+
+ variable x = 3, y = sin(5.6), z = "I think, therefore I am.";
+
+
+
+ Most functions are declared using the define keyword. A simple
+ example is
+
+
+
+ define compute_average (x, y)
+ {
+ variable s = x + y;
+ return s / 2.0;
+ }
+
+
+
+ which defines a function that simply computes the average of two num-
+ bers and returns the result. This example shows that a function con-
+ sists of three parts: the function name, a parameter list, and the
+ function body.
+
+ The parameter list consists of a comma separated list of variable
+ names. It is not necessary to declare variables within a parameter
+ list; they are implicitly declared. However, all other local
+ variables used in the function must be declared. If the function
+ takes no parameters, then the parameter list must still be present,
+ but empty:
+
+
+ define go_left_5 ()
+ {
+ go_left (5);
+ }
+
+
+
+ The last example is a function that takes no arguments and returns no
+ value. Some languages such as PASCAL distinguish such objects from
+ functions that return values by calling these objects procedures.
+ However, S-Lang, like C, does not make such a distinction.
+
+ The language permits recursive functions, i.e., functions that call
+ themselves. The way to do this in S-Lang is to first declare the
+ function using the form:
+
+ define function-name ();
+
+
+ It is not necessary to declare a parameter list when declaring a func-
+ tion in this way.
+
+ The most famous example of a recursive function is the factorial
+ function. Here is how to implement it using S-Lang:
+
+
+ define factorial (); % declare it for recursion
+
+ define factorial (n)
+ {
+ if (n < 2) return 1;
+ return n * factorial (n - 1);
+ }
+
+
+
+ This example also shows how to mix comments with code. S-Lang uses
+ the `%' character to start a comment and all characters from the com-
+ ment character to the end of the line are ignored.
+
+
+
+ 3.2. Strings
+
+
+
+ Perhaps the most appealing feature of any interpreted language is that
+ it frees the user from the responsibility of memory management. This
+ is particularly evident when contrasting how S-Lang handles string
+ variables with a lower level language such as C. Consider a function
+ that concatenates three strings. An example in S-Lang is:
+
+
+ define concat_3_strings (a, b, c)
+ {
+ return strcat (a, strcat (b, c));
+ }
+
+
+
+ This function uses the built-in strcat function for concatenating two
+ strings. In C, the simplest such function would look like:
+
+
+ char *concat_3_strings (char *a, char *b, char *c)
+ {
+ unsigned int len;
+ char *result;
+ len = strlen (a) + strlen (b) + strlen (c);
+ if (NULL == (result = (char *) malloc (len + 1)))
+ exit (1);
+ strcpy (result, a);
+ strcat (result, b);
+ strcat (result, c);
+ return result;
+ }
+
+
+
+ Even this C example is misleading since none of the issues of memory
+ management of the strings has been dealt with. The S-Lang language
+ hides all these issues from the user.
+
+ Binary operators have been defined to work with the string data type.
+ In particular the + operator may be used to perform string
+ concatenation. That is, one can use the + operator as an alternative
+ to strcat:
+
+
+ define concat_3_strings (a, b, c)
+ {
+ return a + b + c;
+ }
+
+
+
+ See section ??? for more information about string variables.
+
+
+
+ 3.3. Referencing and Dereferencing
+
+
+ The unary prefix operator, &, may be used to create a reference to an
+ object, which is similar to a pointer in other languages. References
+ are commonly used as a mechanism to pass a function as an argument to
+ another function as the following example illustrates:
+
+
+ define compute_functional_sum (funct)
+ {
+ variable i, s;
+
+ s = 0;
+ for (i = 0; i < 10; i++)
+ {
+ s += (@funct)(i);
+ }
+ return s;
+ }
+
+ variable sin_sum = compute_functional_sum (&sin);
+ variable cos_sum = compute_functional_sum (&cos);
+
+
+
+ Here, the function compute_functional_sum applies the function speci-
+ fied by the parameter funct to the first 10 integers and returns the
+ sum. The two statements following the function definition show how
+ the sin and cos functions may be used.
+
+ Note the @ operator in the definition of compute_functional_sum. It
+ is known as the dereference operator and is the inverse of the
+ reference operator.
+
+ Another use of the reference operator is in the context of the fgets
+ function. For example,
+
+
+ define read_nth_line (file, n)
+ {
+ variable fp, line;
+ fp = fopen (file, "r");
+
+ while (n > 0)
+ {
+ if (-1 == fgets (&line, fp))
+ return NULL;
+ n--;
+ }
+ return line;
+ }
+
+
+
+ uses the fgets function to read the nth line of a file. In particu-
+ lar, a reference to the local variable line is passed to fgets, and
+ upon return line will be set to the character string read by fgets.
+
+ Finally, references may be used as an alternative to multiple return
+ values by passing information back via the parameter list. The
+ example involving fgets presented above provided an illustration of
+ this. Another example is
+
+
+
+ define set_xyz (x, y, z)
+ {
+ @x = 1;
+ @y = 2;
+ @z = 3;
+ }
+ variable X, Y, Z;
+ set_xyz (&X, &Y, &Z);
+
+
+
+ which, after execution, results in X set to 1, Y set to 2, and Z set
+ to 3. A C programmer will note the similarity of set_xyz to the fol-
+ lowing C implementation:
+
+
+ void set_xyz (int *x, int *y, int *z)
+ {
+ *x = 1;
+ *y = 2;
+ *z = 3;
+ }
+
+
+
+ 3.4. Arrays
+
+
+ The S-Lang language supports multi-dimensional arrays of all
+ datatypes. For example, one can define arrays of references to
+ functions as well as arrays of arrays. Here are a few examples of
+ creating arrays:
+
+
+ variable A = Integer_Type [10];
+ variable B = Integer_Type [10, 3];
+ variable C = [1, 3, 5, 7, 9];
+
+
+
+ The first example creates an array of 10 integers and assigns it to
+ the variable A. The second example creates a 2-d array of 30 integers
+ arranged in 10 rows and 3 columns and assigns the result to B. In the
+ last example, an array of 5 integers is assigned to the variable C.
+ However, in this case the elements of the array are initialized to the
+ values specified. This is known as an inline-array.
+
+ S-Lang also supports something called an range-array. An example of
+ such an array is
+
+
+ variable C = [1:9:2];
+
+
+
+ This will produce an array of 5 integers running from 1 through 9 in
+ increments of 2.
+
+ Arrays are passed by reference to functions and never by value. This
+ permits one to write functions which can initialize arrays. For
+ example,
+
+
+ define init_array (a)
+ {
+ variable i, imax;
+
+ imax = length (a);
+ for (i = 0; i < imax; i++)
+ {
+ a[i] = 7;
+ }
+ }
+
+ variable A = Integer_Type [10];
+ init_array (A);
+
+
+
+ creates an array of 10 integers and initializes all its elements to 7.
+
+ There are more concise ways of accomplishing the result of the
+ previous example. These include:
+
+
+ variable A = [7, 7, 7, 7, 7, 7, 7, 7, 7, 7];
+ variable A = Integer_Type [10]; A[[0:9]] = 7;
+ variable A = Integer_Type [10]; A[*] = 7;
+
+
+
+ The second and third methods use an array of indices to index the
+ array A. In the second, the range of indices has been explicitly
+ specified, whereas the third example uses a wildcard form. See sec-
+ tion ??? for more information about array indexing.
+
+ Although the examples have pertained to integer arrays, the fact is
+ that S-Lang arrays can be of any type, e.g.,
+
+
+ variable A = Double_Type [10];
+ variable B = Complex_Type [10];
+ variable C = String_Type [10];
+ variable D = Ref_Type [10];
+
+
+
+ create 10 element arrays of double, complex, string, and reference
+ types, respectively. The last example may be used to create an array
+ of functions, e.g.,
+
+
+ D[0] = &sin;
+ D[1] = &cos;
+
+
+
+ The language also defines unary, binary, and mathematical operations
+ on arrays. For example, if A and B are integer arrays, then A + B is
+ an array whose elements are the sum of the elements of A and B. A
+ trivial example that illustrates the power of this capability is
+
+ variable X, Y;
+ X = [0:2*PI:0.01];
+ Y = 20 * sin (X);
+
+
+
+ which is equivalent to the highly simplified C code:
+
+
+ double *X, *Y;
+ unsigned int i, n;
+
+ n = (2 * PI) / 0.01 + 1;
+ X = (double *) malloc (n * sizeof (double));
+ Y = (double *) malloc (n * sizeof (double));
+ for (i = 0; i < n; i++)
+ {
+ X[i] = i * 0.01;
+ Y[i] = 20 * sin (X[i]);
+ }
+
+
+
+ 3.5. Structures and User-Defined Types
+
+
+
+ A structure is similar to an array in the sense that it is a container
+ object. However, the elements of an array must all be of the same
+ type (or of Any_Type), whereas a structure is heterogeneous. As an
+ example, consider
+
+
+ variable person = struct
+ {
+ first_name, last_name, age
+ };
+ variable bill = @person;
+ bill.first_name = "Bill";
+ bill.last_name = "Clinton";
+ bill.age = 51;
+
+
+
+ In this example a structure consisting of the three fields has been
+ created and assigned to the variable person. Then an instance of this
+ structure has been created using the dereference operator and assigned
+ to bill. Finally, the individual fields of bill were initialized.
+ This is an example of an anonymous structure.
+
+ A named structure is really a new data type and may be created using
+ the typedef keyword:
+
+
+
+ typedef struct
+ {
+ first_name, last_name, age
+ }
+ Person_Type;
+
+ variable bill = @Person_Type;
+ bill.first_name = "Bill";
+ bill.last_name = "Clinton";
+ bill.age = 51;
+
+
+
+ The big advantage of creating a new type is that one can go on to cre-
+ ate arrays of the data type
+
+
+ variable People = Person_Type [100];
+ People[0].first_name = "Bill";
+ People[1].first_name = "Hillary";
+
+
+
+ The creation and initialization of a structure may be facilitated by a
+ function such as
+
+
+ define create_person (first, last, age)
+ {
+ variable person = @Person_Type;
+ person.first_name = first;
+ person.last_name = last;
+ person.age = age;
+ return person;
+ }
+ variable Bill = create_person ("Bill", "Clinton", 51);
+
+
+
+ Other common uses of structures is the creation of linked lists,
+ binary trees, etc. For more information about these and other
+ features of structures, see section ???.
+
+
+
+ 3.6. Namespaces
+
+
+ In addition to the global namespace, each compilation unit (e.g., a
+ file) is given a private namespace. A variable or function name that
+ is declared using the static keyword will be placed in the private
+ namespace associated with compilation unit. For example,
+
+
+ variable i;
+ static variable i;
+
+
+
+ defines two variables called i. The first declaration defines i in
+ the global namespace, but the second declaration defines i in the pri-
+ vate namespace.
+
+ The -> operator may be used in conjunction with the name of the
+ namespace to access objects in the name space. In the above example,
+ to access the variable i in the global namespace, one would use
+ Global->i. Unless otherwise specified, a private namespace has no
+ name and its objects may not be accessed from outside the compilation
+ unit. However, the implements function may be used give the private
+ namespace a name, allowing access to its objects. For example, if the
+ file t.sl contains
+
+
+ implements ("A");
+ static variable i;
+
+
+
+ then another file may access the variable i via A->i.
+
+
+
+ 4. Data Types and Literal Constants
+
+
+
+ The current implementation of the S-Lang language permits up to 256
+ distinct data types, including predefined data types such as integer
+ and floating point, as well as specialized applications specific data
+ types. It is also possible to create new data types in the language
+ using the typedef mechanism.
+
+ Literal constants are objects such as the integer 3 or the string
+ "hello". The actual data type given to a literal constant depends
+ upon the syntax of the constant. The following sections describe the
+ syntax of literals of specific data types.
+
+
+ 4.1. Predefined Data Types
+
+
+
+ The current version of S-Lang defines integer, floating point,
+ complex, and string types. It also defines special purpose data types
+ such as Null_Type, DataType_Type, and Ref_Type. These types are
+ discussed below.
+
+
+ 4.1.1. Integers
+
+
+
+ The S-Lang language supports both signed and unsigned characters,
+ short integer, long integer, and plain integer types. On most 32 bit
+ systems, there is no difference between an integer and a long integer;
+ however, they may differ on 16 and 64 bit systems. Generally
+ speaking, on a 16 bit system, plain integers are 16 bit quantities
+ with a range of -32767 to 32767. On a 32 bit system, plain integers
+ range from -2147483648 to 2147483647.
+
+ An plain integer literal can be specified in one of several ways:
+
+ o As a decimal (base 10) integer consisting of the characters 0
+ through 9, e.g., 127. An integer specified this way cannot begin
+ with a leading 0. That is, 0127 is not the same as 127.
+
+ o Using hexadecimal (base 16) notation consisting of the characters 0
+ to 9 and A through F. The hexadecimal number must be preceded by
+ the characters 0x. For example, 0x7F specifies an integer using
+ hexadecimal notation and has the same value as decimal 127.
+
+ o In Octal notation using characters 0 through 7. The Octal number
+ must begin with a leading 0. For example, 0177 and 127 represent
+ the same integer.
+
+ Short, long, and unsigned types may be specified by using the
+ proper suffixes: L indicates that the integer is a long integer, h
+ indicates that the integer is a short integer, and U indicates that
+ it is unsigned. For example, 1UL specifies an unsigned long
+ integer.
+
+ Finally, a character literal may be specified using a notation
+ containing a character enclosed in single quotes as 'a'. The value
+ of the character specified this way will lie in the range 0 to 256
+ and will be determined by the ASCII value of the character in
+ quotes. For example,
+
+
+ i = '0';
+
+
+
+ assigns to i the character 48 since the '0' character has an ASCII
+ value of 48.
+
+ Any integer may be preceded by a minus sign to indicate that it is a
+ negative integer.
+
+
+
+ 4.1.2. Floating Point Numbers
+
+
+
+ Single and double precision floating point literals must contain
+ either a decimal point or an exponent (or both). Here are examples of
+ specifying the same double precision point number:
+
+
+ 12. 12.0 12e0 1.2e1 120e-1 .12e2 0.12e2
+
+
+
+ Note that 12 is not a floating point number since it contains neither
+ a decimal point nor an exponent. In fact, 12 is an integer.
+
+ One may append the f character to the end of the number to indicate
+ that the number is a single precision literal.
+
+
+
+ 4.1.3. Complex Numbers
+
+
+
+ The language implements complex numbers as a pair of double precision
+ floating point numbers. The first number in the pair forms the real
+ part, while the second number forms the imaginary part. That is, a
+ complex number may be regarded as the sum of a real number and an
+ imaginary number.
+
+ Strictly speaking, the current implementation of the S-Lang does not
+ support generic complex literals. However, it does support imaginary
+ literals and a more generic complex number with a non-zero real part
+ may be constructed from the imaginary literal via addition of a real
+ number.
+
+ An imaginary literal is specified in the same way as a floating point
+ literal except that i or j is appended. For example,
+
+
+ 12i 12.0i 12e0j
+
+
+
+ all represent the same imaginary number. Actually, 12i is really an
+ imaginary integer except that S-Lang automatically promotes it to a
+ double precision imaginary number.
+
+ A more generic complex number may be constructed from an imaginary
+ literal via addition, e.g.,
+
+
+ 3.0 + 4.0i
+
+
+
+ produces a complex number whose real part is 3.0 and whose imaginary
+ part is 4.0.
+
+ The intrinsic functions Real and Imag may be used to retrieve the real
+ and imaginary parts of a complex number, respectively.
+
+
+
+ 4.1.4. Strings
+
+
+
+ A string literal must be enclosed in double quotes as in:
+
+
+ "This is a string".
+
+
+
+ Although there is no imposed limit on the length of a string, string
+ literals must be less than 256 characters in length. It is possible
+ to go beyond this limit by string concatenation, e.g.,
+
+
+ "This is the first part of a long string"
+ + "and this is the second half"
+
+
+
+ Any character except a newline (ASCII 10) or the null character (ASCII
+ 0) may appear explicitly in a string literal. However, these charac-
+ ters may be used implicitly using the mechanism described below.
+
+ The backslash character is a special character and is used to include
+ other special characters (such as a newline character) in the string.
+ The special characters recognized are:
+
+
+ \" -- double quote
+ \' -- single quote
+ \\ -- backslash
+ \a -- bell character (ASCII 7)
+ \t -- tab character (ASCII 9)
+ \n -- newline character (ASCII 10)
+ \e -- escape character (ASCII 27)
+ \xhhh -- character expressed in HEXADECIMAL notation
+ \ooo -- character expressed in OCTAL notation
+ \dnnn -- character expressed in DECIMAL
+
+
+
+ For example, to include the double quote character as part of the
+ string, it must be preceded by a backslash character, e.g.,
+ "This is a \"quote\""
+
+
+
+ Similarly, the next illustrates how a newline character may be
+ included:
+
+
+ "This is the first line\nand this is the second"
+
+
+
+ 4.1.5. Null_Type
+
+
+ Objects of type Null_Type can have only one value: NULL. About the
+ only thing that you can do with this data type is to assign it to
+ variables and test for equality with other objects. Nevertheless,
+ Null_Type is an important and extremely useful data type. Its main
+ use stems from the fact that since it can be compared for equality
+ with any other data type, it is ideal to represent the value of an
+ object which does not yet have a value, or has an illegal value.
+
+ As a trivial example of its use, consider
+
+
+ define add_numbers (a, b)
+ {
+ if (a == NULL) a = 0;
+ if (b == NULL) b = 0;
+ return a + b;
+ }
+ variable c = add_numbers (1, 2);
+ variable d = add_numbers (1, NULL);
+ variable e = add_numbers (1,);
+ variable f = add_numbers (,);
+
+
+
+ It should be clear that after these statements have been executed, c
+ will have a value of 3. It should also be clear that d will have a
+ value of 1 because NULL has been passed as the second parameter. One
+ feature of the language is that if a parameter has been omitted from a
+ function call, the variable associated with that parameter will be set
+ to NULL. Hence, e and f will be set to 1 and 0, respectively.
+
+ The Null_Type data type also plays an important role in the context of
+ structures.
+
+
+ 4.1.6. Ref_Type
+
+ Objects of Ref_Type are created using the unary reference operator &.
+ Such objects may be dereferenced using the dereference operator @.
+ For example,
+
+
+ variable sin_ref = &sin;
+ variable y = (@sin_ref) (1.0);
+
+ creates a reference to the sin function and assigns it to sin_ref.
+ The second statement uses the dereference operator to call the func-
+ tion that sin_ref references.
+
+ The Ref_Type is useful for passing functions as arguments to other
+ functions, or for returning information from a function via its
+ parameter list. The dereference operator is also used to create an
+ instance of a structure. For these reasons, further discussion of
+ this important type can be found in section ??? and section ???.
+
+
+ 4.1.7. Array_Type and Struct_Type
+
+
+ Variables of type Array_Type and Struct_Type are known as container
+ objects. They are much more complicated than the simple data types
+ discussed so far and each obeys a special syntax. For these reasons
+ they are discussed in a separate chapters. See ???.
+
+
+ 4.1.8. DataType_Type Type
+
+
+
+ S-Lang defines a type called DataType_Type. Objects of this type have
+ values that are type names. For example, an integer is an object of
+ type Integer_Type. The literals of DataType_Type include:
+
+
+ Char_Type (signed character)
+ UChar_Type (unsigned character)
+ Short_Type (short integer)
+ UShort_Type (unsigned short integer)
+ Integer_Type (plain integer)
+ UInteger_Type (plain unsigned integer)
+ Long_Type (long integer)
+ ULong_Type (unsigned long integer)
+ Float_Type (single precision real)
+ Double_Type (double precision real)
+ Complex_Type (complex numbers)
+ String_Type (strings, C strings)
+ BString_Type (binary strings)
+ Struct_Type (structures)
+ Ref_Type (references)
+ Null_Type (NULL)
+ Array_Type (arrays)
+ DataType_Type (data types)
+
+
+
+ as well as the names of any other types that an application defines.
+
+ The built-in function typeof returns the data type of its argument,
+ i.e., a DataType_Type. For instance typeof(7) returns Integer_Type
+ and typeof(Integer_Type) returns DataType_Type. One can use this
+ function as in the following example:
+
+
+ if (Integer_Type == typeof (x)) message ("x is an integer");
+
+
+
+ The literals of DataType_Type have other uses as well. One of the
+ most common uses of these literals is to create arrays, e.g.,
+ x = Complex_Type [100];
+
+
+
+ creates an array of 100 complex numbers and assigns it to x.
+
+
+
+ 4.2. Typecasting: Converting from one Type to Another
+
+
+ Occasionally, it is necessary to convert from one data type to
+ another. For example, if you need to print an object as a string, it
+ may be necessary to convert it to a String_Type. The typecast
+ function may be used to perform such conversions. For example,
+ consider
+
+
+ variable x = 10, y;
+ y = typecast (x, Double_Type);
+
+
+
+ After execution of these statements, x will have the integer value 10
+ and y will have the double precision floating point value 10.0. If
+ the object to be converted is an array, the typecast function will act
+ upon all elements of the array. For example,
+
+
+ variable x = [1:10]; % Array of integers
+ variable y = typecast (x, Double_Type);
+
+
+
+ will create an array of 10 double precision values and assign it to y.
+ One should also realize that it is not always possible to perform a
+ typecast. For example, any attempt to convert an Integer_Type to a
+ Null_Type will result in a run-time error.
+
+ Often the interpreter will perform implicit type conversions as
+ necessary to complete calculations. For example, when multiplying an
+ Integer_Type with a Double_Type, it will convert the Integer_Type to a
+ Double_Type for the purpose of the calculation. Thus, the example
+ involving the conversion of an array of integers to an array of
+ doubles could have been performed by multiplication by 1.0, i.e.,
+
+
+ variable x = [1:10]; % Array of integers
+ variable y = 1.0 * x;
+
+
+
+ The string intrinsic function is similar to the typecast function
+ except that it converts an object to a string representation. It is
+ important to understand that a typecast from some type to String_Type
+ is not the same as converting an object to its string operation.
+ That is, typecast(x,String_Type) is not equivalent to string(x). The
+ reason for this is that when given an array, the typecast function
+ acts on each element of the array to produce another array, whereas
+ the string function produces a a string.
+ The string function is useful for printing the value of an object.
+ This use is illustrated in the following simple example:
+
+
+ define print_object (x)
+ {
+ message (string (x));
+ }
+
+
+
+ Here, the message function has been used because it writes a string to
+ the display. If the string function was not used and the message
+ function was passed an integer, a type-mismatch error would have
+ resulted.
+
+
+
+ 5. Identifiers
+
+
+
+ The names given to variables, functions, and data types are called
+ identifiers. There are some restrictions upon the actual characters
+ that make up an identifier. An identifier name must start with a
+ letter ([A-Za-z]), an underscore character, or a dollar sign. The
+ rest of the characters in the name can be any combination of letters,
+ digits, dollar signs, or underscore characters. However, all
+ identifiers whose name begins with two underscore characters are
+ reserved for internal use by the interpreter and declarations of
+ objects with such names should be avoided.
+
+ Examples of valid identifiers include:
+
+
+ mary _3 _this_is_ok
+ a7e1 $44 _44$_Three
+
+
+
+ However, the following are not legal:
+
+
+ 7abc 2e0 #xx
+
+
+
+ In fact, 2e0 actually specifies the real number 2.0.
+
+ Although the maximum length of identifiers is unspecified by the
+ language, the length should be kept below 64 characters.
+
+ The following identifiers are reserved by the language for use as
+ keywords:
+
+
+ !if _for do mod sign xor
+ ERROR_BLOCK abs do_while mul2 sqr public
+ EXIT_BLOCK and else not static private
+ USER_BLOCK0 andelse exch or struct
+ USER_BLOCK1 break for orelse switch
+ USER_BLOCK2 case foreach pop typedef
+ USER_BLOCK3 chs forever return using
+ USER_BLOCK4 continue if shl variable
+ __tmp define loop shr while
+
+
+
+ In addition, the next major S-Lang release (v2.0) will reserve try and
+ catch, so it is probably a good idea to avoid those words until then.
+
+
+
+ 6. Variables
+
+
+
+ A variable must be declared before it can be used, otherwise an
+ undefined name error will be generated. A variable is declared using
+ the variable keyword, e.g,
+
+
+ variable x, y, z;
+
+
+
+ declares three variables, x, y, and z. This is an example of a vari-
+ able declaration statement, and like all statements, it must end in a
+ semi-colon.
+
+ Variables declared this way are untyped and inherit a type upon
+ assignment. The actual type checking is performed at run-time. For
+ example,
+
+
+ x = "This is a string";
+ x = 1.2;
+ x = 3;
+ x = 2i;
+
+
+
+ results in x being set successively to a string, a float, an integer,
+ and to a complex number (0+2i). Any attempt to use a variable before
+ it has acquired a type will result in an uninitialized variable error.
+
+ It is legal to put executable code in a variable declaration list.
+ That is,
+
+
+ variable x = 1, y = sin (x);
+
+
+
+ are legal variable declarations. This also provides a convenient way
+ of initializing a variable.
+
+ Variables are classified as either global or local. A variable
+ declared inside a function is said to be local and has no meaning
+ outside the function. A variable is said to be global if it was
+ declared outside a function. Global variables are further classified
+ as being public, static, or private, according to the name space where
+ they were defined. See chapter ??? for more information about name
+ spaces.
+
+ The following global variables are predefined by the language and are
+ mainly used as convenience variables:
+
+
+ $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+
+
+ An intrinsic variable is another type of global variable. Such
+ variables have a definite type which cannot be altered. Variables of
+ this type may also be defined to be read-only, or constant variables.
+ An example of an intrinsic variable is PI which is a read-only double
+ precision variable with a value of approximately
+ 3.14159265358979323846.
+
+
+
+ 7. Operators
+
+
+
+ S-Lang supports a variety of operators that are grouped into three
+ classes: assignment operators, binary operators, and unary operators.
+
+ An assignment operator is used to assign a value to a variable. They
+ will be discussed more fully in the context of the assignment
+ statement in section ???.
+
+ An unary operator acts only upon a single quantity while a binary
+ operation is an operation between two quantities. The boolean
+ operator not is an example of an unary operator. Examples of binary
+ operators include the usual arithmetic operators +, -, *, and /. The
+ operator given by - can be either an unary operator (negation) or a
+ binary operator (subtraction); the actual operation is determined from
+ the context in which it is used.
+
+ Binary operators are used in algebraic forms, e.g., a + b. Unary
+ operators fall in one of two classes: postfix-unary or prefix-unary.
+ For example, in the expression -x, the minus sign is a prefix-unary
+ operator.
+
+ Not all data types have binary or unary operations defined. For
+ example, while String_Type objects support the + operator, they do not
+ admit the * operator.
+
+
+ 7.1. Unary Operators
+
+
+ The unary operators operate only upon a single operand. They include:
+ not, ~, -, @, &, as well as the increment and decrement operators ++
+ and --, respectively.
+
+ The boolean operator not acts only upon integers and produces 0 if its
+ operand is non-zero, otherwise it produces 1.
+
+ The bit-level not operator ~ performs a similar function, except that
+ it operates on the individual bits of its integer operand.
+
+ The arithmetic negation operator - is the most well-known unary
+ operator. It simply reverses the sign of its operand.
+
+ The reference (&) and dereference (@) operators will be discussed in
+ greater detail in section ???. Similarly, the increment (++) and
+ decrement (--) operators will be discussed in the context of the
+ assignment operator.
+
+
+ 7.2. Binary Operators
+
+
+
+ The binary operators may be grouped according to several classes:
+ arithmetic operators, relational operators, boolean operators, and
+ bitwise operators.
+
+ All binary and unary operators may be overloaded. For example, the
+ arithmetic plus operator has been overloaded by the String_Type data
+ type to permit concatenation between strings.
+
+
+
+ 7.2.1. Arithmetic Operators
+
+
+
+ The arithmetic operators include +, -, *, /, which perform addition,
+ subtraction, multiplication, and division, respectively. In addition
+ to these, S-Lang supports the mod operator as well as the power
+ operator ^.
+
+ The data type of the result produced by the use of one of these
+ operators depends upon the data types of the binary participants. If
+ they are both integers, the result will be an integer. However, if
+ the operands are not of the same type, they will be converted to a
+ common type before the operation is performed. For example, if one is
+ a floating point value and the other is an integer, the integer will
+ be converted to a float. In general, the promotion from one type to
+ another is such that no information is lost, if possible. As an
+ example, consider the expression 8/5 which indicates division of the
+ integer 8 by the integer 5. The result will be the integer 1 and not
+ the floating point value 1.6. However, 8/5.0 will produce 1.6 because
+ 5.0 is a floating point number.
+
+
+
+ 7.2.2. Relational Operators
+
+
+
+ The relational operators are >, >=, <, <=, ==, and !=. These perform
+ the comparisons greater than, greater than or equal, less than, less
+ than or equal, equal, and not equal, respectively. The result of one
+ of these comparisons is the integer 1 if the comparison is true, or 0
+ if the comparison is false. For example, 6 >= 5 returns 1, but 6 == 5
+ produces 0.
+
+
+
+ 7.2.3. Boolean Operators
+
+
+ There are only two boolean binary operators: or and and. These
+ operators are defined only for integers and produce an integer result.
+ The or operator returns 1 if either of its operands are non-zero,
+ otherwise it produces 0. The and operator produces 1 if and only if
+ both its operands are non-zero, otherwise it produces 0.
+
+ Neither of these operators perform the so-called boolean short-circuit
+ evaluation. For example, consider the expression:
+
+
+ (x != 0) and (1/x > 10)
+
+
+
+ Here, if x were to have a value of zero, a division by zero error
+ would occur because even though x!=0 evaluates to zero, the and opera-
+ tor is not short-circuited and the 1/x expression would still be eval-
+ uated. Although these operators are not short-circuited, S-Lang does
+ have another mechanism of performing short-circuit boolean evaluation
+ via the orelse and andelse expressions. See below for information
+ about these constructs.
+
+
+ 7.2.4. Bitwise Operators
+
+
+
+ The bitwise binary operators are defined only with integer operands
+ and are used for bit-level operations. Operators that fall in this
+ class include &, |, shl, shr, and xor. The & operator performs a
+ boolean AND operation between the corresponding bits of the operands.
+ Similarly, the | operator performs the boolean OR operation on the
+ bits. The bit-shifting operators shl and shr shift the bits of the
+ first operand by the number given by the second operand to the left or
+ right, respectively. Finally, the xor performs an EXCLUSIVE-OR
+ operation.
+
+ These operators are commonly used to manipulate variables whose
+ individual bits have distinct meanings. In particular, & is usually
+ used to test bits, | can be used to set bits, and xor may be used to
+ flip a bit.
+
+ As an example of using & to perform tests on bits, consider the
+ following: The jed text editor stores some of the information about a
+ buffer in a bitmapped integer variable. The value of this variable
+ may be retrieved using the jed intrinsic function getbuf_info, which
+ actually returns four quantities: the buffer flags, the name of the
+ buffer, directory name, and file name. For the purposes of this
+ section, only the buffer flags are of interest and can be retrieved
+ via a function such as
+
+
+ define get_buffer_flags ()
+ {
+ variable flags;
+ (,,,flags) = getbuf_info ();
+ return flags;
+ }
+
+
+
+ The buffer flags is a bitmapped quantity where the 0th bit indicates
+ whether or not the buffer has been modified, the first bit indicates
+ whether or not autosave has been enabled for the buffer, and so on.
+ Consider for the moment the task of determining if the buffer has been
+ modified. This can be determined by looking at the zeroth bit, if it
+ is 0 the buffer has not been modified, otherwise it has. Thus we can
+ create the function,
+
+
+ define is_buffer_modified ()
+ {
+ variable flags = get_buffer_flags ();
+ return (flags & 1);
+ }
+
+
+
+ where the integer 1 has been used since it has all of its bits set to
+ 0, except for the zeroth one, which is set to 1. (At this point, it
+ should also be apparent that bits are numbered from zero, thus an 8
+ bit integer consists of bits 0 to 7, where 0 is the least significant
+ bit and 7 is the most significant one.) Similarly, we can create
+ another function
+
+
+
+ define is_autosave_on ()
+ {
+ variable flags = get_buffer_flags ();
+ return (flags & 2);
+ }
+
+
+
+ to determine whether or not autosave has been turned on for the
+ buffer.
+
+ The shl operator may be used to form the integer with only the nth bit
+ set. For example, 1 shl 6 produces an integer with all bits set to
+ zero except the sixth bit, which is set to one. The following example
+ exploits this fact:
+
+
+ define test_nth_bit (flags, nth)
+ {
+ return flags & (1 shl nth);
+ }
+
+
+
+ 7.2.5. Namespace operator
+
+ The operator -> is used to in conjunction with the name of a namespace
+ to access an object within the namespace. For example, if A is the
+ name of a namespace containing the variable v, then A->v refers to
+ that variable.
+
+
+ 7.2.6. Operator Precedence
+
+
+
+ 7.2.7. Binary Operators and Functions Returning Multiple Values
+
+
+ Care must be exercised when using binary operators with an operand the
+ returns multiple values. In fact, the current implementation of the
+ S-Lang language will produce incorrect results if both operands of a
+ binary expression return multiple values. At most, only one of
+ operands of a binary expression can return multiple values, and that
+ operand must be the first one, not the second. For example,
+
+
+ define read_line (fp)
+ {
+ variable line, status;
+
+ status = fgets (&line, fp);
+ if (status == -1)
+ return -1;
+ return (line, status);
+ }
+
+
+
+ defines a function, read_line that takes a single argument, a handle
+ to an open file, and returns one or two values, depending upon the
+ return value of fgets. Now consider
+
+
+ while (read_line (fp) > 0)
+ {
+ text = ();
+ % Do something with text
+ .
+ .
+ }
+
+
+
+ Here the relational binary operator > forms a comparison between one
+ of the return values (the one at the top of the stack) and 0. In
+ accordance with the above rule, since read_line returns multiple val-
+ ues, it occurs as the left binary operand. Putting it on the right as
+ in
+
+
+ while (0 < read_line (fp)) % Incorrect
+ {
+ text = ();
+ % Do something with text
+ .
+ .
+ }
+
+
+
+ violates the rule and will result in the wrong answer.
+
+
+
+ 7.3. Mixing Integer and Floating Point Arithmetic
+
+
+ If a binary operation (+, -, * , /) is performed on two integers, the
+ result is an integer. If at least one of the operands is a float, the
+ other is converted to float and the result is float. For example:
+
+
+ 11 / 2 --> 5 (integer)
+ 11 / 2.0 --> 5.5 (float)
+ 11.0 / 2 --> 5.5 (float)
+ 11.0 / 2.0 --> 5.5 (float)
+
+
+
+ Finally note that only integers may be used as array indices, loop
+ control variables, and bit operations. The conversion functions, int
+ and float, may be used convert between floats and ints where appropri-
+ ate, e.g.,
+
+
+ int (1.5) --> 1 (integer)
+ float(1.5) --> 1.5 (float)
+ float (1) --> 1.0 (float)
+
+ 7.4. Short Circuit Boolean Evaluation
+
+
+ The boolean operators or and and are not short circuited as they are
+ in some languages. S-Lang uses orelse and andelse expressions for
+ short circuit boolean evaluation. However, these are not binary
+ operators. Expressions of the form:
+
+ expr-1 and expr-2 and ... expr-n
+
+
+ can be replaced by the short circuited version using andelse:
+
+ andelse {expr-1} {expr-2} ... {expr-n}
+
+
+ A similar syntax holds for the orelse operator. For example, consider
+ the statement:
+
+
+ if ((x != 0) and (1/x > 10)) do_something ();
+
+
+
+ Here, if x were to have a value of zero, a division by zero error
+ would occur because even though x!=0 evaluates to zero, the and opera-
+ tor is not short circuited and the 1/x expression would be evaluated
+ causing division by zero. For this case, the andelse expression could
+ be used to avoid the problem:
+
+
+ if (andelse
+ {x != 0}
+ {1 / x > 10}) do_something ();
+
+
+
+ 8. Statements
+
+
+
+ Loosely speaking, a statement is composed of expressions that are
+ grouped according to the syntax or grammar of the language to express
+ a complete computation. Statements are analogous to sentences in a
+ human language and expressions are like phrases. All statements in
+ the S-Lang language must end in a semi-colon.
+
+ A statement that occurs within a function is executed only during
+ execution of the function. However, statements that occur outside the
+ context of a function are evaluated immediately.
+
+ The language supports several different types of statements such as
+ assignment statements, conditional statements, and so forth. These
+ are described in detail in the following sections.
+
+
+ 8.1. Variable Declaration Statements
+
+ Variable declarations were already discussed in chapter ???. For the
+ sake of completeness, a variable declaration is a statement of the
+ form
+
+ variable variable-declaration-list ;
+
+
+ where the variable-declaration-list is a comma separated list of one
+ or more variable names with optional initializations, e.g.,
+
+
+ variable x, y = 2, z;
+
+
+
+ 8.2. Assignment Statements
+
+
+
+ Perhaps the most well known form of statement is the assignment
+ statement. Statements of this type consist of a left-hand side, an
+ assignment operator, and a right-hand side. The left-hand side must
+ be something to which an assignment can be performed. Such an object
+ is called an lvalue.
+
+ The most common assignment operator is the simple assignment operator
+ =. Simple of its use include
+
+
+ x = 3;
+ x = some_function (10);
+ x = 34 + 27/y + some_function (z);
+ x = x + 3;
+
+
+
+ In addition to the simple assignment operator, S-Lang also supports
+ the assignment operators += and -=. Internally, S-Lang transforms
+
+
+ a += b;
+
+
+ to
+
+
+ a = a + b;
+
+
+
+ Similarly, a -= b is transformed to a = a - b. It is extremely impor-
+ tant to realize that, in general, a+b is not equal to b+a. This means
+ that a+=b is not the same as a=b+a. As an example consider
+
+
+ a = "hello"; a += "world";
+
+
+
+ After execution of these two statements, a will have the value "hel-
+ loworld" and not "worldhello".
+
+ Since adding or subtracting 1 from a variable is quite common, S-Lang
+ also supports the unary increment and decrement operators ++, and --,
+ respectively. That is, for numeric data types,
+
+
+ x = x + 1;
+ x += 1;
+ x++;
+
+
+
+ are all equivalent. Similarly,
+
+
+ x = x - 1;
+ x -= 1;
+ x--;
+
+
+
+ are also equivalent.
+
+ Strictly speaking, ++ and -- are unary operators. When used as x++,
+ the ++ operator is said to be a postfix-unary operator. However, when
+ used as ++x it is said to be a prefix-unary operator. The current
+ implementation does not distinguish between the two forms, thus x++
+ and ++x are equivalent. The reason for this equivalence is that
+ assignment expressions do not return a value in the S-Lang language as
+ they do in C. Thus one should exercise care and not try to write C-
+ like code such as
+
+
+ x = 10;
+ while (--x) do_something (x); % Ok in C, but not in S-Lang
+
+
+
+ The closest valid S-Lang form involves a comma-expression:
+
+
+
+ x = 10;
+ while (x--, x) do_something (x); % Ok in S-Lang and in C
+
+
+
+ S-Lang also supports a multiple-assignment statement. It is discussed
+ in detail in section ???.
+
+
+
+ 8.3. Conditional and Looping Statements
+
+
+
+ S-Lang supports a wide variety of conditional and looping statements.
+ These constructs operate on statements grouped together in blocks. A
+ block is a sequence of S-Lang statements enclosed in braces and may
+ contain other blocks. However, a block cannot include function
+ declarations. In the following, statement-or-block refers to either a
+ single S-Lang statement or to a block of statements, and integer-
+ expression is an integer-valued expression. next-statement represents
+ the statement following the form under discussion.
+
+
+ 8.3.1. Conditional Forms
+
+
+
+ 8.3.1.1. if
+
+ The simplest condition statement is the if statement. It follows the
+ syntax
+
+ if (integer-expression) statement-or-block next-statement
+
+
+ If integer-expression evaluates to a non-zero result, then the state-
+ ment or group of statements implied statement-or-block will get exe-
+ cuted. Otherwise, control will proceed to next-statement.
+
+ An example of the use of this type of conditional statement is
+
+
+ if (x != 0)
+ {
+ y = 1.0 / x;
+ if (x > 0) z = log (x);
+ }
+
+
+
+ This example illustrates two if statements where the second if state-
+ ment is part of the block of statements that belong to the first.
+
+
+ 8.3.1.2. if-else
+
+ Another form of if statement is the if-else statement. It follows the
+ syntax:
+
+ if (integer-expression) statement-or-block-1 else statement-or-block-2
+ next-statement
+
+ Here, if expression returns non-zero, statement-or-block-1 will get
+ executed and control will pass on to next-statement. However, if
+ expression returns zero, statement-or-block-2 will get executed before
+ continuing with next-statement. A simple example of this form is
+
+
+ if (x > 0) z = log (x); else error ("x must be positive");
+
+
+
+ Consider the more complex example:
+
+
+ if (city == "Boston")
+ if (street == "Beacon") found = 1;
+ else if (city == "Madrid")
+ if (street == "Calle Mayor") found = 1;
+ else found = 0;
+
+
+
+ This example illustrates a problem that beginners have with if-else
+ statements. The grammar presented above shows that the this example
+ is equivalent to
+
+
+ if (city == "Boston")
+ {
+ if (street == "Beacon") found = 1;
+ else if (city == "Madrid")
+ {
+ if (street == "Calle Mayor") found = 1;
+ else found = 0;
+ }
+ }
+
+
+
+ It is important to understand the grammar and not be seduced by the
+ indentation!
+
+
+ 8.3.1.3. !if
+
+
+ One often encounters if statements similar to
+
+ if (integer-expression == 0) statement-or-block
+
+
+ or equivalently,
+
+ if (not(integer-expression)) statement-or-block
+
+
+ The !if statement was added to the language to simplify the handling
+ of such statements. It obeys the syntax
+
+ !if (integer-expression) statement-or-block
+
+
+ and is functionally equivalent to
+
+ if (not (expression)) statement-or-block
+
+
+
+ 8.3.1.4. orelse, andelse
+
+
+ These constructs were discussed earlier. The syntax for the orelse
+ statement is:
+
+ orelse {integer-expression-1} ... {integer-expression-n}
+
+
+ This causes each of the blocks to be executed in turn until one of
+ them returns a non-zero integer value. The result of this statement
+ is the integer value returned by the last block executed. For exam-
+ ple,
+
+
+ orelse { 0 } { 6 } { 2 } { 3 }
+
+
+
+ returns 6 since the second block is the first to return a non-zero
+ result. The last two block will not get executed.
+
+ The syntax for the andelse statement is:
+
+ andelse {integer-expression-1} ... {integer-expression-n}
+
+
+ Each of the blocks will be executed in turn until one of them returns
+ a zero value. The result of this statement is the integer value
+ returned by the last block executed. For example,
+
+
+ andelse { 6 } { 2 } { 0 } { 4 }
+
+
+
+ returns 0 since the third block will be the last to execute.
+
+
+ 8.3.1.5. switch
+
+ The switch statement deviates the most from its C counterpart. The
+ syntax is:
+
+
+ switch (x)
+ { ... : ...}
+ .
+ .
+ { ... : ...}
+
+
+
+ The `:' operator is a special symbol which means to test the top item
+ on the stack, and if it is non-zero, the rest of the block will get
+ executed and control will pass out of the switch statement. Other-
+ wise, the execution of the block will be terminated and the process
+ will be repeated for the next block. If a block contains no : opera-
+ tor, the entire block is executed and control will pass onto the next
+ statement following the switch statement. Such a block is known as
+ the default case.
+
+ As a simple example, consider the following:
+
+
+ switch (x)
+ { x == 1 : message("Number is one.");}
+ { x == 2 : message("Number is two.");}
+ { x == 3 : message("Number is three.");}
+ { x == 4 : message("Number is four.");}
+ { x == 5 : message("Number is five.");}
+ { message ("Number is greater than five.");}
+
+
+
+ Suppose x has an integer value of 3. The first two blocks will termi-
+ nate at the `:' character because each of the comparisons with x will
+ produce zero. However, the third block will execute to completion.
+ Similarly, if x is 7, only the last block will execute in full.
+
+ A more familiar way to write the previous example used the case
+ keyword:
+
+
+ switch (x)
+ { case 1 : print("Number is one.");}
+ { case 2 : print("Number is two.");}
+ { case 3 : print("Number is three.");}
+ { case 4 : print("Number is four.");}
+ { case 5 : print("Number is five.");}
+ { print ("Number is greater than five.");}
+
+
+
+ The case keyword is a more useful comparison operator because it can
+ perform a comparison between different data types while using == may
+ result in a type-mismatch error. For example,
+
+
+ switch (x)
+ { (x == 1) or (x == "one") : print("Number is one.");}
+ { (x == 2) or (x == "two") : print("Number is two.");}
+ { (x == 3) or (x == "three") : print("Number is three.");}
+ { (x == 4) or (x == "four") : print("Number is four.");}
+ { (x == 5) or (x == "five") : print("Number is five.");}
+ { print ("Number is greater than five.");}
+
+
+
+ will fail because the == operation is not defined between strings and
+ integers. The correct way to write this to use the case keyword:
+
+
+ switch (x)
+ { case 1 or case "one" : print("Number is one.");}
+ { case 2 or case "two" : print("Number is two.");}
+ { case 3 or case "three" : print("Number is three.");}
+ { case 4 or case "four" : print("Number is four.");}
+ { case 5 or case "five" : print("Number is five.");}
+ { print ("Number is greater than five.");}
+
+
+ 8.3.2. Looping Forms
+
+
+
+ 8.3.2.1. while
+
+ The while statement follows the syntax
+
+ while (integer-expression) statement-or-block next-statement
+
+
+ It simply causes statement-or-block to get executed as long as inte-
+ ger-expression evaluates to a non-zero result. For example,
+
+
+ i = 10;
+ while (i)
+ {
+ i--;
+ newline ();
+ }
+
+
+
+ will cause the newline function to get called 10 times. However,
+
+
+ i = -10;
+ while (i)
+ {
+ i--;
+ newline ();
+ }
+
+
+
+ would loop forever (or until i wraps from the most negative integer
+ value to the most positive and then decrements to zero).
+
+
+ If you are a C programmer, do not let the syntax of the language
+ seduce you into writing this example as you would in C:
+
+
+ i = 10;
+ while (i--) newline ();
+
+
+
+ The fact is that expressions such as i-- do not return a value in S-
+ Lang as they do in C. If you must write this way, use the comma oper-
+ ator as in
+
+
+ i = 10;
+ while (i, i--) newline ();
+
+
+
+ 8.3.2.2. do...while
+
+ The do...while statement follows the syntax
+
+ do statement-or-block while (integer-expression);
+
+
+ The main difference between this statement and the while statement is
+ that the do...while form performs the test involving integer-expres-
+ sion after each execution of statement-or-block rather than before.
+ This guarantees that statement-or-block will get executed at least
+ once.
+
+ A simple example from the jed editor follows:
+
+
+ bob (); % Move to beginning of buffer
+ do
+ {
+ indent_line ();
+ }
+ while (down (1));
+
+
+
+ This will cause all lines in the buffer to get indented via the jed
+ intrinsic function indent_line.
+
+
+ 8.3.2.3. for
+
+ Perhaps the most complex looping statement is the for statement;
+ nevertheless, it is a favorite of many programmers. This statement
+ obeys the syntax
+
+ for (init-expression; integer-expression; end-expression) statement-
+ or-block next-statement
+
+
+ In addition to statement-or-block, its specification requires three
+ other expressions. When executed, the for statement evaluates init-
+ expression, then it tests integer-expression. If integer-expression
+ returns zero, control passes to next-statement. Otherwise, it exe-
+ cutes statement-or-block as long as integer-expression evaluates to a
+ non-zero result. After every execution of statement-or-block, end-
+ expression will get evaluated.
+
+ This statement is almost equivalent to
+
+ init-expression; while (integer-expression) { statement-or-block end-
+ expression; }
+
+
+ The reason that they are not fully equivalent involves what happens
+ when statement-or-block contains a continue statement.
+
+ Despite the apparent complexity of the for statement, it is very easy
+ to use. As an example, consider
+
+
+ s = 0;
+ for (i = 1; i <= 10; i++) s += i;
+
+
+
+ which computes the sum of the first 10 integers.
+
+
+ 8.3.2.4. loop
+
+ The loop statement simply executes a block of code a fixed number of
+ times. It follows the syntax
+
+ loop (integer-expression) statement-or-block next-statement
+
+
+ If the integer-expression evaluates to a positive integer, statement-
+ or-block will get executed that many times. Otherwise, control will
+ pass to next-statement.
+
+ For example,
+
+
+ loop (10) newline ();
+
+
+
+ will cause the function newline to get called 10 times.
+
+
+ 8.3.2.5. _.ds h for loop
+
+ Like loop, the _for statement simply executes a block of code a fixed
+ number times. Unlike the loop statement, the _for loop is useful in
+ situations where the loop index is needed. It obeys the syntax
+
+ _for (first-value, last-value, increment) block next-statement
+
+
+ Each time through the loop, the current value of the loop index is
+ pushed onto the stack. The first time through, the loop index will
+ have the value of first-value. The second time its value will be
+ first-value + increment, and so on. The loop will terminate when the
+ value of the loop index exceeds last-value. The current implementa-
+ tion requires the control parameters first-value, last-value, and
+ increment to be integered valued expressions.
+
+ For example, it may be used to compute the sum of the first ten
+ integers:
+
+
+ s = 0;
+ _for (1, 10, 1)
+ {
+ i = ();
+ s += i;
+ }
+
+
+
+ The execution speed of the _for loop is more than twice as fast as the
+ more powerful for loop making it a better choice for many situations.
+
+
+ 8.3.2.6. forever
+
+ The forever statement is similar to the loop statement except that it
+ loops forever, or until a break or a return statement is executed. It
+ obeys the syntax
+ forever statement-or-block
+
+
+ A trivial example of this statement is
+
+
+ n = 10;
+ forever
+ {
+ if (n == 0) break;
+ newline ();
+ n--;
+ }
+
+
+
+ 8.3.2.7. foreach
+
+ The foreach statement is used to loop over one or more statements for
+ every element in a container object. A container object is a data
+ type that consists of other types. Examples include both ordinary and
+ associative arrays, structures, and strings. Every time through the
+ loop the current member of the object is pushed onto the stack.
+
+ The simple type of foreach statement obeys the syntax
+
+ foreach (container-object) statement-or-block
+
+
+ Here container-object can be an expression that returns a container
+ object. A simple example is
+
+
+ foreach (["apple", "peach", "pear"])
+ {
+ fruit = ();
+ process_fruit (fruit);
+ }
+
+
+
+ This example shows that if the container object is an array, then suc-
+ cessive elements of the array are pushed onto the stack prior to each
+ execution cycle. If the container object is a string, then successive
+ characters of the string are pushed onto the stack.
+
+ What actually gets pushed onto the stack may be controlled via the
+ using form of the foreach statement. This more complex type of
+ foreach statement follows the syntax
+
+ foreach ( container-object ) using ( control-list ) statement-or-block
+
+
+ The allowed values of control-list will depend upon the type of con-
+ tainer object. For associative arrays (Assoc_Type), control-list
+ specified whether keys, values, or both are pushed onto the stack.
+ For example,
+
+
+
+ foreach (a) using ("keys")
+ {
+ k = ();
+ .
+ .
+ }
+
+
+
+ results in the keys of the associative array a being pushed on the
+ list. However,
+
+
+ foreach (a) using ("values")
+ {
+ v = ();
+ .
+ .
+ }
+
+
+
+ will cause the values to be used, and
+
+
+ foreach (a) using ("keys", "values")
+ {
+ (k,v) = ();
+ .
+ .
+ }
+
+
+
+ will use both the keys and values of the array.
+
+ Similarly, for linked-lists of structures, one may walk the list via
+ code like
+
+
+ foreach (linked_list) using ("next")
+ {
+ s = ();
+ .
+ .
+ }
+
+
+
+ This foreach statement is equivalent
+
+
+ s = linked_list;
+ while (s != NULL)
+ {
+ .
+ .
+ s = s.next;
+ }
+
+
+
+ Consult the type-specific documentation for a discussion of the using
+ control words, if any, appropriate for a given type.
+
+
+ 8.4. break, return, continue
+
+
+ S-Lang also includes the non-local transfer functions return, break,
+ and continue. The return statement causes control to return to the
+ calling function while the break and continue statements are used in
+ the context of loop structures. Consider:
+
+
+ define fun ()
+ {
+ forever
+ {
+ s1;
+ s2;
+ ..
+ if (condition_1) break;
+ if (condition_2) return;
+ if (condition_3) continue;
+ ..
+ s3;
+ }
+ s4;
+ ..
+ }
+
+
+
+ Here, a function fun has been defined that contains a forever loop
+ consisting of statements s1, s2,...,s3, and three if statements. As
+ long as the expressions condition_1, condition_2, and condition_3
+ evaluate to zero, the statements s1, s2,...,s3 will be repeatedly exe-
+ cuted. However, if condition_1 returns a non-zero value, the break
+ statement will get executed, and control will pass out of the forever
+ loop to the statement immediately following the loop which in this
+ case is s4. Similarly, if condition_2 returns a non-zero number, the
+ return statement will cause control to pass back to the caller of fun.
+ Finally, the continue statement will cause control to pass back to the
+ start of the loop, skipping the statement s3 altogether.
+
+
+
+ 9. Functions
+
+
+
+ A function may be thought of as a group of statements that work
+ together to perform a computation. While there are no imposed limits
+ upon the number statements that may occur within a function, it is
+ considered poor programming practice if a function contains many
+ statements. This notion stems from the belief that a function should
+ have a simple, well defined purpose.
+
+
+ 9.1. Declaring Functions
+
+
+
+ Like variables, functions must be declared before they can be used.
+ The define keyword is used for this purpose. For example,
+
+
+ define factorial ();
+
+
+
+ is sufficient to declare a function named factorial. Unlike the vari-
+ able keyword used for declaring variables, the define keyword does not
+ accept a list of names.
+
+ Usually, the above form is used only for recursive functions. In most
+ cases, the function name is almost always followed by a parameter list
+ and the body of the function:
+
+ define function-name (parameter-list) { statement-list }
+
+
+ The function-name is an identifier and must conform to the naming
+ scheme for identifiers discussed in chapter ???. The parameter-list
+ is a comma-separated list of variable names that represent parameters
+ passed to the function, and may be empty if no parameters are to be
+ passed. The body of the function is enclosed in braces and consists
+ of zero or more statements (statement-list).
+
+ The variables in the parameter-list are implicitly declared, thus,
+ there is no need to declare them via a variable declaration statement.
+ In fact any attempt to do so will result in a syntax error.
+
+
+
+ 9.2. Parameter Passing Mechanism
+
+
+
+ Parameters to a function are always passed by value and never by
+ reference. To see what this means, consider
+
+
+ define add_10 (a)
+ {
+ a = a + 10;
+ }
+ variable b = 0;
+ add_10 (b);
+
+
+ Here a function add_10 has been defined, which when executed, adds 10
+ to its parameter. A variable b has also been declared and initialized
+ to zero before it is passed to add_10. What will be the value of b
+ after the call to add_10? If S-Lang were a language that passed
+ parameters by reference, the value of b would be changed to 10. How-
+ ever, S-Lang always passes by value, which means that b would retain
+ its value of zero after the function call.
+
+ S-Lang does provide a mechanism for simulating pass by reference via
+ the reference operator. See the next section for more details.
+
+ If a function is called with a parameter in the parameter list
+ omitted, the corresponding variable in the function will be set to
+ NULL. To make this clear, consider the function
+
+
+ define add_two_numbers (a, b)
+ {
+ if (a == NULL) a = 0;
+ if (b == NULL) b = 0;
+ return a + b;
+ }
+
+
+
+ This function must be called with two parameters. However, we can
+ omit one or both of the parameters by calling it in one of the follow-
+ ing ways:
+
+
+ variable s = add_two_numbers (2,3);
+ variable s = add_two_numbers (2,);
+ variable s = add_two_numbers (,3);
+ variable s = add_two_numbers (,);
+
+
+
+ The first example calls the function using both parameters; however,
+ at least one of the parameters was omitted in the other examples. The
+ interpreter will implicitly convert the last three examples to
+
+
+ variable s = add_two_numbers (2, NULL);
+ variable s = add_two_numbers (NULL, 3);
+ variable s = add_two_numbers (NULL, NULL);
+
+
+
+ It is important to note that this mechanism is available only for
+ function calls that specify more than one parameter. That is,
+
+
+ variable s = add_10 ();
+
+
+
+ is not equivalent to add_10(NULL). The reason for this is simple: the
+ parser can only tell whether or not NULL should be substituted by
+ looking at the position of the comma character in the parameter list,
+ and only function calls that indicate more than one parameter will use
+ a comma. A mechanism for handling single parameter function calls is
+ described in the next section.
+ 9.3. Referencing Variables
+
+
+
+ One can achieve the effect of passing by reference by using the
+ reference (&) and dereference (@) operators. Consider again the add_10
+ function presented in the previous section. This time we write it as
+
+
+ define add_10 (a)
+ {
+ @a = @a + 10;
+ }
+ variable b = 0;
+ add_10 (&b);
+
+
+
+ The expression &b creates a reference to the variable b and it is the
+ reference that gets passed to add_10. When the function add_10 is
+ called, the value of a will be a reference to b. It is only by deref-
+ erencing this value that b can be accessed and changed. So, the
+ statement @a=@a+10; should be read `add 10' to the value of the object
+ that a references and assign the result to the object that a refer-
+ ences.
+
+ The reader familiar with C will note the similarity between references
+ in S-Lang and pointers in C.
+
+ One of the main purposes for references is that this mechanism allows
+ reference to functions to be passed to other functions. As a simple
+ example from elementary calculus, consider the following function
+ which returns an approximation to the derivative of another function
+ at a specified point:
+
+
+ define derivative (f, x)
+ {
+ variable h = 1e-6;
+ return ((@f)(x+h) - (@f)(x)) / h;
+ }
+
+
+
+ It can be used to differentiate the function
+
+
+ define x_squared (x)
+ {
+ return x^2;
+ }
+
+
+
+ at the point x = 3 via the expression derivative(&x_squared,3).
+
+
+
+ 9.4. Functions with a Variable Number of Arguments
+
+
+
+ S-Lang functions may be defined to take a variable number of
+ arguments. The reason for this is that the calling routine pushes the
+ arguments onto the stack before making a function call, and it is up
+ to the called function to pop the values off the stack and make
+ assignments to the variables in the parameter list. These details
+ are, for the most part, hidden from the programmer. However, they are
+ important when a variable number of arguments are passed.
+
+ Consider the add_10 example presented earlier. This time it is
+ written
+
+
+ define add_10 ()
+ {
+ variable x;
+ x = ();
+ return x + 10;
+ }
+ variable s = add_10 (12); % ==> s = 22;
+
+
+
+ For the uninitiated, this example looks as if it is destined for dis-
+ aster. The add_10 function looks like it accepts zero arguments, yet
+ it was called with a single argument. On top of that, the assignment
+ to x looks strange. The truth is, the code presented in this example
+ makes perfect sense, once you realize what is happening.
+
+ First, consider what happened when add_10 is called with the the
+ parameter 12. Internally, 12 is pushed onto the stack and then the
+ function called. Now, consider the function itself. x is a variable
+ local to the function. The strange looking assignment `x=()' simply
+ takes whatever is on the stack and assigns it to x. In other words,
+ after this statement, the value of x will be 12, since 12 will be at
+ the top of the stack.
+
+ A generic function of the form
+
+
+ define function_name (x, y, ..., z)
+ {
+ .
+ .
+ }
+
+
+
+ is internally transformed by the interpreter to
+
+
+
+ define function_name ()
+ {
+ variable x, y, ..., z;
+ z = ();
+ .
+ .
+ y = ();
+ x = ();
+ .
+ .
+ }
+
+
+
+ before further parsing. (The add_10 function, as defined above, is
+ already in this form.) With this knowledge in hand, one can write a
+ function that accepts a variable number of arguments. Consider the
+ function:
+
+
+ define average_n (n)
+ {
+ variable x, y;
+ variable s;
+
+ if (n == 1)
+ {
+ x = ();
+ s = x;
+ }
+ else if (n == 2)
+ {
+ y = ();
+ x = ();
+ s = x + y;
+ }
+ else error ("average_n: only one or two values supported");
+
+ return s / n;
+ }
+ variable ave1 = average_n (3.0, 1); % ==> 3.0
+ variable ave2 = average_n (3.0, 5.0, 2); % ==> 4.0
+
+
+
+ Here, the last argument passed to average_n is an integer reflecting
+ the number of quantities to be averaged. Although this example works
+ fine, its principal limitation is obvious: it only supports one or two
+ values. Extending it to three or more values by adding more else if
+ constructs is rather straightforward but hardly worth the effort.
+ There must be a better way, and there is:
+
+
+
+ define average_n (n)
+ {
+ variable s, x;
+ s = 0;
+ loop (n)
+ {
+ x = (); % get next value from stack
+ s += x;
+ }
+ return s / n;
+ }
+
+
+
+ The principal limitation of this approach is that one must still pass
+ an integer that specifies how many values are to be averaged.
+
+ Fortunately, a special variable exists that is local to every function
+ and contains the number of values that were passed to the function.
+ That variable has the name _NARGS and may be used as follows:
+
+
+ define average_n ()
+ {
+ variable x, s = 0;
+
+ if (_NARGS == 0) error ("Usage: ave = average_n (x, ...);");
+
+ loop (_NARGS)
+ {
+ x = ();
+ s += x;
+ }
+ return s / _NARGS;
+ }
+
+
+
+ Here, if no arguments are passed to the function, a simple message
+ that indicates how it is to be used is printed out.
+
+
+
+ 9.5. Returning Values
+
+
+ As stated earlier, the usual way to return values from a function is
+ via the return statement. This statement has the simple syntax
+
+ return expression-list ;
+
+
+ where expression-list is a comma separated list of expressions. If
+ the function does not return any values, the expression list will be
+ empty. As an example of a function that can return multiple values,
+ consider
+
+
+
+ define sum_and_diff (x, y)
+ {
+ variable sum, diff;
+
+ sum = x + y; diff = x - y;
+ return sum, diff;
+ }
+
+
+
+ which is a function returning two values.
+
+ It is extremely important to note that the calling routine must
+ explicitly handle all values returned by a function. Although some
+ languages such as C do not have this restriction, S-Lang does and it
+ is a direct result of a S-Lang function's ability to return many
+ values and accept a variable number of parameters. Examples of
+ properly handling the above function include
+
+
+ variable s, d;
+ (s, d) = sum_and_diff (5, 4); % ignore neither
+ (s,) = sum_and_diff (5, 4); % ignore diff
+ (,) = sum_and_diff (5, 4); % ignore both sum and diff
+
+
+
+ See the section below on assignment statements for more information
+ about this important point.
+
+
+ 9.6. Multiple Assignment Statement
+
+
+
+ S-Lang functions can return more than one value, e.g.,
+
+
+ define sum_and_diff (x, y)
+ {
+ return x + y, x - y;
+ }
+
+
+
+ returns two values. It accomplishes this by placing both values on
+ the stack before returning. If you understand how S-Lang functions
+ handle a variable number of parameters (section ???), then it should
+ be rather obvious that one assigns such values to variables. One way
+ is to use, e.g.,
+
+
+ sum_and_diff (9, 4);
+ d = ();
+ s = ();
+
+
+
+ However, the most convenient way to accomplish this is to use a
+ multiple assignment statement such as
+
+
+ (s, d) = sum_and_diff (9, 4);
+
+
+
+ The most general form of the multiple assignment statement is
+
+
+ ( var_1, var_2, ..., var_n ) = expression;
+
+
+
+ In fact, internally the interpreter transforms this statement into the
+ form
+
+
+ expression; var_n = (); ... var_2 = (); var_1 = ();
+
+
+
+ for further processing.
+
+ If you do not care about one of return values, simply omit the
+ variable name from the list. For example,
+
+
+ (s, ) = sum_and_diff (9, 4);
+
+
+
+ assigns the sum of 9 and 4 to s and the difference (9-4) will be
+ removed from the stack.
+
+ As another example, the jed editor provides a function called down
+ that takes an integer argument and returns an integer. It is used to
+ move the current editing position down the number of lines specified
+ by the argument passed to it. It returns the number of lines it
+ successfully moved the editing position. Often one does not care
+ about the return value from this function. Although it is always
+ possible to handle the return value via
+
+
+ variable dummy = down (10);
+
+
+
+ it is more convenient to use a multiple assignment expression and omit
+ the variable name, e.g.,
+
+
+ () = down (10);
+
+
+
+ Some functions return a variable number of values instead of a fixed
+ number. Usually, the value at the top of the stack will indicate the
+ actual number of return values. For such functions, the multiple
+ assignment statement cannot directly be used. To see how such
+ functions can be dealt with, consider the following function:
+
+
+ define read_line (fp)
+ {
+ variable line;
+ if (-1 == fgets (&line, fp))
+ return -1;
+ return (line, 0);
+ }
+
+
+
+ This function returns either one or two values, depending upon the
+ return value of fgets. Such a function may be handled as in the fol-
+ lowing example:
+
+
+ status = read_line (fp);
+ if (status != -1)
+ {
+ s = ();
+ .
+ .
+ }
+
+
+
+ In this example, the last value returned by read_line is assigned to
+ status and then tested. If it is non-zero, the second return value is
+ assigned to s. In particular note the empty set of parenthesis in the
+ assignment to s. This simply indicates that whatever is on the top of
+ the stack when the statement is executed will be assigned to s.
+
+ Before leaving this section it is important to reiterate the fact that
+ if a function returns a value, the caller must deal with that return
+ value. Otherwise, the value will continue to live onto the stack and
+ may eventually lead to a stack overflow error. Failing to handle the
+ return value of a function is the most common mistake that
+ inexperienced S-Lang programmers make. For example, the fflush
+ function returns a value that many C programmer's never check.
+ Instead of writing
+
+
+ fflush (fp);
+
+
+
+ as one could in C, a S-Lang programmer should write
+
+
+ () = fflush (fp);
+
+
+
+ in S-Lang. (Many good C programmer's write (void)fflush(fp) to indi-
+ cate that the return value is being ignored).
+
+
+
+ 9.7. Exit-Blocks
+
+
+
+ An exit-block is a set of statements that get executed when a
+ functions returns. They are very useful for cleaning up when a
+ function returns via an explicit call to return from deep within a
+ function.
+
+ An exit-block is created by using the EXIT_BLOCK keyword according to
+ the syntax
+
+ EXIT_BLOCK { statement-list }
+
+
+ where statement-list represents the list of statements that comprise
+ the exit-block. The following example illustrates the use of an exit-
+ block:
+
+
+ define simple_demo ()
+ {
+ variable n = 0;
+
+ EXIT_BLOCK { message ("Exit block called."); }
+
+ forever
+ {
+ if (n == 10) return;
+ n++;
+ }
+ }
+
+
+
+ Here, the function contains an exit-block and a forever loop. The
+ loop will terminate via the return statement when n is 10. Before it
+ returns, the exit-block will get executed.
+
+ A function can contain multiple exit-blocks, but only the last one
+ encountered during execution will actually get executed. For example,
+
+
+ define simple_demo (n)
+ {
+ EXIT_BLOCK { return 1; }
+
+ if (n != 1)
+ {
+ EXIT_BLOCK { return 2; }
+ }
+ return;
+ }
+
+
+
+ If 1 is passed to this function, the first exit-block will get exe-
+ cuted because the second one would not have been encountered during
+ the execution. However, if some other value is passed, the second
+ exit-block would get executed. This example also illustrates that it
+ is possible to explicitly return from an exit-block, although nested
+ exit-blocks are illegal.
+
+
+
+ 10. Name Spaces
+
+
+
+ By default, all global variables and functions are defined in the
+ global namespace. In addition to the global namespace, every
+ compilation unit (e.g., a file containing S-Lang code) has an
+ anonymous namespace. Objects may be defined in the anonymous
+ namespace via the static declaration keyword. For example,
+
+
+ static variable x;
+ static define hello () { message ("hello"); }
+
+
+
+ defines a variable x and a function hello in the anonymous namespace.
+ This is useful when one wants to define functions and variables that
+ are only to be used within the file, or more precisely the compilation
+ unit, that defines them.
+
+ The implements function may be used to give the anonymous namespace a
+ name to allow access to its objects from outside the compilation unit
+ that defines them. For example,
+
+
+ implements ("foo");
+ static variable x;
+
+
+
+ allows the variable x to be accessed via foo->x, e.g.,
+
+
+ if (foo->x == 1) foo->x = 2;
+
+
+
+ The implements function does more than simply giving the anonymous
+ namespace a name. It also changes the default variable and function
+ declaration mode from public to static. That is,
+
+
+ implements ("foo");
+ variable x;
+
+
+
+ and
+
+
+ implements ("foo");
+ static variable x;
+
+
+
+ are equivalent. Then to create a public object within the namespace,
+ one must explicitly use the public keyword.
+
+ Finally, the private keyword may be used to create an object that is
+ truly private within the compilation unit. For example,
+ implements ("foo");
+ variable x;
+ private variable y;
+
+
+
+ allows x to be accessed from outside the namespace via foo->x, however
+ y cannot be accessed.
+
+
+
+ 11. Arrays
+
+
+
+ An array is a container object that can contain many values of one
+ data type. Arrays are very useful objects and are indispensable for
+ certain types of programming. The purpose of this chapter is to
+ describe how arrays are defined and used in the S-Lang language.
+
+
+ 11.1. Creating Arrays
+
+
+
+ The S-Lang language supports multi-dimensional arrays of all data
+ types. Since the Array_Type is a data type, one can even have arrays
+ of arrays. To create a multi-dimensional array of SomeType use the
+ syntax
+
+
+ SomeType [dim0, dim1, ..., dimN]
+
+
+
+ Here dim0, dim1, ... dimN specify the size of the individual dimen-
+ sions of the array. The current implementation permits arrays consist
+ of up to 7 dimensions. When a numeric array is created, all its ele-
+ ments are initialized to zero. The initialization of other array
+ types depend upon the data type, e.g., String_Type and Struct_Type
+ arrays are initialized to NULL.
+
+ As a concrete example, consider
+
+
+ a = Integer_Type [10];
+
+
+
+ which creates a one-dimensional array of 10 integers and assigns it to
+ a. Similarly,
+
+
+ b = Double_Type [10, 3];
+
+
+
+ creates a 30 element array of double precision numbers arranged in 10
+ rows and 3 columns, and assigns it to b.
+
+
+ 11.1.1. Range Arrays
+
+
+ There is a more convenient syntax for creating and initializing a 1-d
+ arrays. For example, to create an array of ten integers whose
+ elements run from 1 through 10, one may simply use:
+
+
+ a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+
+
+
+ Similarly,
+
+
+ b = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
+
+
+
+ specifies an array of ten doubles.
+
+ An even more compact way of specifying a numeric array is to use a
+ range-array. For example,
+
+
+ a = [0:9];
+
+
+
+ specifies an array of 10 integers whose elements range from 0 through
+ 9. The most general form of a range array is
+
+
+ [first-value : last-value : increment]
+
+
+
+ where the increment is optional and defaults to 1. This creates an
+ array whose first element is first-value and whose successive values
+ differ by increment. last-value sets an upper limit upon the last
+ value of the array as described below.
+
+ If the range array [a:b:c] is integer valued, then the interval
+ specified by a and b is closed. That is, the kth element of the array
+ x_k is given by x_k=a+ck and must satisfy a<=x_k<=b. Hence, the
+ number of elements in an integer range array is given by the
+ expression 1 + (b-a)/c.
+
+ The situation is somewhat more complicated for floating point range
+ arrays. The interval specified by a floating point range array
+ [a:b:c] is semi-open such that b is not contained in the interval. In
+ particular, the kth element of [a:b:c] is given by x_k=a+kc such that
+ a<=x_k<b when c>=0, and b<x_k<=a otherwise. The number of elements in
+ the array is one greater than the largest k that satisfies the open
+ interval constraint.
+
+ Here are a few examples that illustrate the above comments:
+
+
+ [1:5:1] ==> [1,2,3,4,5]
+ [1.0:5.0:1.0] ==> [1.0, 2.0, 3.0, 4.0]
+ [5:1:-1] ==> [5,4,3,2,1]
+ [5.0:1.0:-1.0] ==> [5.0, 4.0, 3.0, 2.0];
+ [1:1] ==> [1]
+ [1.0:1.0] ==> []
+ [1:-3] ==> []
+
+
+
+ 11.1.2. Creating arrays via the dereference operator
+
+
+
+ Another way to create an array is apply the dereference operator @ to
+ the DataType_Type literal Array_Type. The actual syntax for this
+ operation resembles a function call
+
+ variable a = @Array_Type (data-type, integer-array);
+
+
+ where data-type is of type DataType_Type and integer-array is a 1-d
+ array of integers that specify the size of each dimension. For exam-
+ ple,
+
+
+ variable a = @Array_Type (Double_Type, [10, 20]);
+
+
+
+ will create a 10 by 20 array of doubles and assign it to a. This
+ method of creating arrays derives its power from the fact that it is
+ more flexible than the methods discussed in this section. We shall
+ encounter it again in section ??? in the context of the array_info
+ function.
+
+
+
+ 11.2. Reshaping Arrays
+
+
+ It is sometimes possible to change the `shape' of an array using the
+ reshape function. For example, a 1-d 10 element array may be reshaped
+ into a 2-d array consisting of 5 rows and 2 columns. The only
+ restriction on the operation is that the arrays must be commensurate.
+ The reshape function follows the syntax
+
+ reshape (array-name, integer-array);
+
+
+ where array-name specifies the array to be reshaped to have the dimen-
+ sions given by integer-array, a 1-dimensional array of integers. It
+ is important to note that this does not create a new array, it simply
+ reshapes the existing array. Thus,
+
+
+ variable a = Double_Type [100];
+ reshape (a, [10, 10]);
+
+
+
+ turns a into a 10 by 10 array.
+
+
+
+ 11.3. Indexing Arrays
+
+
+ An individual element of an array may be referred to by its index.
+ For example, a[0] specifies the zeroth element of the one dimensional
+ array a, and b[3,2] specifies the element in the third row and second
+ column of the two dimensional array b. As in C array indices are
+ numbered from 0. Thus if a is a one-dimensional array of ten
+ integers, the last element of the array is given by a[9]. Using a[10]
+ would result in a range error.
+
+ A negative index may be used to index from the end of the array, with
+ a[-1] referring to the last element of a, a[-2] referring to the next
+ to the last element, and so on.
+
+ One may use the indexed value like any other variable. For example,
+ to set the third element of an integer array to 6, use
+
+
+ a[2] = 6;
+
+
+
+ Similarly, that element may be used in an expression, such as
+
+
+ y = a[2] + 7;
+
+
+
+ Unlike other S-Lang variables which inherit a type upon assignment,
+ array elements already have a type. For example, an attempt to assign
+ a string value to an element of an integer array will result in a
+ type-mismatch error.
+
+ One may use any integer expression to index an array. A simple
+ example that computes the sum of the elements of 10 element 1-d array
+ is
+
+
+ variable i, s;
+ s = 0;
+ for (i = 0; i < 10; i++) s += a[i];
+
+
+
+ However, if the built-in sum function is available (not all programs
+ using S-Lang support this), then it should be used to compute the sum
+ of an array, e.g.,
+
+
+ s = sum(a);
+
+
+
+ Unlike many other languages, S-Lang permits arrays to be indexed by
+ other integer arrays. Suppose that a is a 1-d array of 10 doubles.
+ Now consider:
+
+
+ i = [6:8];
+ b = a[i];
+
+
+
+ Here, i is a 1-dimensional range array of three integers with i[0]
+ equal to 6, i[1] equal to 7, and i[2] equal to 8. The statement b =
+ a[i]; will create a 1-d array of three doubles and assign it to b.
+ The zeroth element of b, b[0] will be set to the sixth element of a,
+ or a[6], and so on. In fact, these two simple statements are equiva-
+ lent to
+
+ b = Double_Type [3];
+ b[0] = a[6];
+ b[1] = a[7];
+ b[2] = a[8];
+
+
+
+ except that using an array of indices is not only much more conve-
+ nient, but executes much faster.
+
+ More generally, one may use an index array to specify which elements
+ are to participate in a calculation. For example, consider
+
+
+ a = Double_Type [1000];
+ i = [0:499];
+ j = [500:999];
+ a[i] = -1.0;
+ a[j] = 1.0;
+
+
+
+ This creates an array of 1000 doubles and sets the first 500 elements
+ to -1.0 and the last 500 to 1.0. Actually, one may do away with the i
+ and j variables altogether and use
+
+
+ a = Double_Type [1000];
+ a [[0:499]] = -1.0;
+ a [[500:999]] = 1.0;
+
+
+
+ It is important to understand the syntax used and, in particular, to
+ note that a[[0:499]] is not the same as a[0:499]. In fact, the latter
+ will generate a syntax error.
+
+ Often, it is convenient to use a rubber range to specify indices. For
+ example, a[[500:]] specifies all elements of a whose index is greater
+ than or equal to 500. Similarly, a[[:499]] specifies the first 500
+ elements of a. Finally, a[[:]] specifies all the elements of a;
+ however, using a[*] is more convenient.
+
+ One should be careful when using index arrays with negative elements.
+ As pointed out above, a negative index is used to index from the end
+ of the array. That is, a[-1] refers to the last element of a. How
+ should a[[[0:-1]] be interpreted? By itself, [0:-1] is an empty
+ array; hence, one might expect a[[0:-1]] to refer to no elements.
+ However, when used in an array indexing context, [0:-1] is interpreted
+ as an array indexing the first through the last elements of the array.
+ While this is a very convenient mechanism to specifiy the last 3
+ elements of an array using a[[-3:-1]], it is very easy to forget these
+ semantics.
+
+ Now consider a multi-dimensional array. For simplicity, suppose that
+ a is a 100 by 100 array of doubles. Then the expression a[0, *]
+ specifies all elements in the zeroth row. Similarly, a[*, 7]
+ specifies all elements in the seventh column. Finally, a[[3:5][6:12]]
+ specifies the 3 by 7 region consisting of rows 3, 4, and 5, and
+ columns 6 through 12 of a.
+
+ We conclude this section with a few examples.
+
+ Here is a function that computes the trace (sum of the diagonal
+ elements) of a square 2 dimensional n by n array:
+
+
+ define array_trace (a, n)
+ {
+ variable s = 0, i;
+ for (i = 0; i < n; i++) s += a[i, i];
+ return s;
+ }
+
+
+
+ This fragment creates a 10 by 10 integer array, sets its diagonal ele-
+ ments to 5, and then computes the trace of the array:
+
+
+ a = Integer_Type [10, 10];
+ for (j = 0; j < 10; j++) a[j, j] = 5;
+ the_trace = array_trace(a, 10);
+
+
+
+ We can get rid of the for loop as follows:
+
+
+ j = Integer_Type [10, 2];
+ j[*,0] = [0:9];
+ j[*,1] = [0:9];
+ a[j] = 5;
+
+
+
+ Here, the goal was to construct a 2-d array of indices that correspond
+ to the diagonal elements of a, and then use that array to index a. To
+ understand how this works, consider the middle statements. They are
+ equivalent to the following for loops:
+
+
+ variable i;
+ for (i = 0; i < 10; i++) j[i, 0] = i;
+ for (i = 0; i < 10; i++) j[i, 1] = i;
+
+
+
+ Thus, row n of j will have the value (n,n), which is precisely what
+ was sought.
+
+ Another example of this technique is the function:
+
+
+ define unit_matrix (n)
+ {
+ variable a = Integer_Type [n, n];
+ variable j = Integer_Type [n, 2];
+ j[*,0] = [0:n - 1];
+ j[*,1] = [0:n - 1];
+
+ a[j] = 1;
+ return a;
+ }
+
+ This function creates an n by n unit matrix, that is a 2-d n by n
+ array whose elements are all zero except on the diagonal where they
+ have a value of 1.
+
+
+
+ 11.4. Arrays and Variables
+
+
+ When an array is created and assigned to a variable, the interpreter
+ allocates the proper amount of space for the array, initializes it,
+ and then assigns to the variable a reference to the array. So, a
+ variable that represents an array has a value that is really a
+ reference to the array. This has several consequences, some good and
+ some bad. It is believed that the advantages of this representation
+ outweigh the disadvantages. First, we shall look at the positive
+ aspects.
+
+ When a variable is passed to a function, it is always the value of the
+ variable that gets passed. Since the value of a variable representing
+ an array is a reference, a reference to the array gets passed. One
+ major advantage of this is rather obvious: it is a fast and efficient
+ way to pass the array. This also has another consequence that is
+ illustrated by the function
+
+
+ define init_array (a, n)
+ {
+ variable i;
+
+ for (i = 0; i < n; i++) a[i] = some_function (i);
+ }
+
+
+
+ where some_function is a function that generates a scalar value to
+ initialize the ith element. This function can be used in the follow-
+ ing way:
+
+
+ variable X = Double_Type [100000];
+ init_array (X, 100000);
+
+
+
+ Since the array is passed to the function by reference, there is no
+ need to make a separate copy of the 100000 element array. As pointed
+ out above, this saves both execution time and memory. The other
+ salient feature to note is that any changes made to the elements of
+ the array within the function will be manifested in the array outside
+ the function. Of course, in this case, this is a desirable side-
+ effect.
+
+ To see the downside of this representation, consider:
+
+
+ variable a, b;
+ a = Double_Type [10];
+ b = a;
+ a[0] = 7;
+
+
+ What will be the value of b[0]? Since the value of a is really a ref-
+ erence to the array of ten doubles, and that reference was assigned to
+ b, b also refers to the same array. Thus any changes made to the ele-
+ ments of a, will also be made implicitly to b.
+
+ This begs the question: If the assignment of one variable which
+ represents an array, to another variable results in the assignment of
+ a reference to the array, then how does one make separate copies of
+ the array? There are several answers including using an index array,
+ e.g., b = a[*]; however, the most natural method is to use the
+ dereference operator:
+
+
+ variable a, b;
+ a = Double_Type [10];
+ b = @a;
+ a[0] = 7;
+
+
+
+ In this example, a separate copy of a will be created and assigned to
+ b. It is very important to note that S-Lang never implicitly derefer-
+ ences an object. So, one must explicitly use the dereference opera-
+ tor. This means that the elements of a dereferenced array are not
+ themselves dereferenced. For example, consider dereferencing an array
+ of arrays, e.g.,
+
+
+ variable a, b;
+ a = Array_Type [2];
+ a[0] = Double_Type [10];
+ a[1] = Double_Type [10];
+ b = @a;
+
+
+
+ In this example, b[0] will be a reference to the array that a[0] ref-
+ erences because a[0] was not explicitly dereferenced.
+
+
+ 11.5. Using Arrays in Computations
+
+
+
+ Many functions and operations work transparently with arrays. For
+ example, if a and b are arrays, then the sum a + b is an array whose
+ elements are formed from the sum of the corresponding elements of a
+ and b. A similar statement holds for all other binary and unary
+ operations.
+
+ Let's consider a simple example. Suppose, that we wish to solve a set
+ of n quadratic equations whose coefficients are given by the 1-d
+ arrays a, b, and c. In general, the solution of a quadratic equation
+ will be two complex numbers. For simplicity, suppose that all we
+ really want is to know what subset of the coefficients, a, b, c,
+ correspond to real-valued solutions. In terms of for loops, we can
+ write:
+
+
+
+ variable i, d, index_array;
+ index_array = Integer_Type [n];
+ for (i = 0; i < n; i++)
+ {
+ d = b[i]^2 - 4 * a[i] * c[i];
+ index_array [i] = (d >= 0.0);
+ }
+
+
+
+ In this example, the array index_array will contain a non-zero value
+ if the corresponding set of coefficients has a real-valued solution.
+ This code may be written much more compactly and with more clarity as
+ follows:
+
+
+ variable index_array = ((b^2 - 4 * a * c) >= 0.0);
+
+
+
+ S-Lang has a powerful built-in function called where. This function
+ takes an array of integers and returns a 2-d array of indices that
+ correspond to where the elements of the input array are non-zero.
+ This simple operation is extremely useful. For example, suppose a is a
+ 1-d array of n doubles, and it is desired to set to zero all elements
+ of the array whose value is less than zero. One way is to use a for
+ loop:
+
+
+ for (i = 0; i < n; i++)
+ if (a[i] < 0.0) a[i] = 0.0;
+
+
+
+ If n is a large number, this statement can take some time to execute.
+ The optimal way to achieve the same result is to use the where func-
+ tion:
+
+
+ a[where (a < 0.0)] = 0;
+
+
+
+ Here, the expression (a < 0.0) returns an array whose dimensions are
+ the same size as a but whose elements are either 1 or 0, according to
+ whether or not the corresponding element of a is less than zero. This
+ array of zeros and ones is then passed to where which returns a 2-d
+ integer array of indices that indicate where the elements of a are
+ less than zero. Finally, those elements of a are set to zero.
+
+ As a final example, consider once more the example involving the set
+ of n quadratic equations presented above. Suppose that we wish to get
+ rid of the coefficients of the previous example that generated non-
+ real solutions. Using an explicit for loop requires code such as:
+
+
+
+ variable i, j, nn, tmp_a, tmp_b, tmp_c;
+
+ nn = 0;
+ for (i = 0; i < n; i++)
+ if (index_array [i]) nn++;
+
+ tmp_a = Double_Type [nn];
+ tmp_b = Double_Type [nn];
+ tmp_c = Double_Type [nn];
+
+ j = 0;
+ for (i = 0; i < n; i++)
+ {
+ if (index_array [i])
+ {
+ tmp_a [j] = a[i];
+ tmp_b [j] = b[i];
+ tmp_c [j] = c[i];
+ j++;
+ }
+ }
+ a = tmp_a;
+ b = tmp_b;
+ c = tmp_c;
+
+
+
+ Not only is this a lot of code, it is also clumsy and error-prone.
+ Using the where function, this task is trivial:
+
+
+ variable i;
+ i = where (index_array != 0);
+ a = a[i];
+ b = b[i];
+ c = c[i];
+
+
+
+ All the examples up to now assumed that the dimensions of the array
+ were known. Although the intrinsic function length may be used to get
+ the total number of elements of an array, it cannot be used to get the
+ individual dimensions of a multi-dimensional array. However, the
+ function array_info may be used to get information about an array,
+ such as its data type and size. The function returns three values:
+ the data type, the number of dimensions, and an integer array
+ containing the size of each dimension. It may be used to determine
+ the number of rows of an array as follows:
+
+
+ define num_rows (a)
+ {
+ variable dims, type, num_dims;
+
+ (dims, num_dims, type) = array_info (a);
+ return dims[0];
+ }
+
+
+
+ The number of columns may be obtained in a similar manner:
+
+
+ define num_cols (a)
+ {
+ variable dims, type, num_dims;
+
+ (dims, num_dims, type) = array_info (a);
+ if (num_dims > 1) return dims[1];
+ return 1;
+ }
+
+
+
+ Another use of array_info is to create an array that has the same
+ number of dimensions as another array:
+
+
+ define make_int_array (a)
+ {
+ variable dims, num_dims, type;
+
+ (dims, num_dims, type) = array_info (a);
+ return @Array_Type (Integer_Type, dims);
+ }
+
+
+
+ 12. Associative Arrays
+
+
+
+ An associative array differs from an ordinary array in the sense that
+ its size is not fixed and that is indexed by a string, called the key.
+ For example, consider:
+
+
+ variable A = Assoc_Type [Integer_Type];
+ A["alpha"] = 1;
+ A["beta"] = 2;
+ A["gamma"] = 3;
+
+
+
+ Here, A represents an associative array of integers (Integer_Type) and
+ three keys have been added to the array.
+
+ As the example suggests, an associative array may be created using one
+ of the following forms:
+
+ Assoc_Type [type] Assoc_Type [type, default-value] Assoc_Type []
+
+
+ The last form returns an associative array of Any_Type objects allow-
+ ing any type of object to may be stored in the array.
+
+ The form involving a default-value is useful for associating a default
+ value for non-existent array members. This feature is explained in
+ more detail below.
+
+ There are several functions that are specially designed to work with
+ associative arrays. These include:
+
+ o assoc_get_keys, which returns an ordinary array of strings
+ containing the keys in the array.
+
+
+ o assoc_get_values, which returns an ordinary array of the values of
+ the associative array.
+
+
+ o assoc_key_exists, which can be used to determine whether or not a
+ key exists in the array.
+
+ o assoc_delete_key, which may be used to remove a key (and its value)
+ from the array.
+
+ To illustrate the use of an associative array, consider the problem of
+ counting the number of repeated occurrences of words in a list. Let
+ the word list be represented as an array of strings given by
+ word_list. The number of occurrences of each word may be stored in an
+ associative array as follows:
+
+
+
+ variable a, word;
+ a = Assoc_Type [Integer_Type];
+ foreach (word_list)
+ {
+ word = ();
+ if (0 == assoc_key_exists (a, word))
+ a[word] = 0;
+ a[word]++; % same as a[word] = a[word] + 1;
+ }
+
+
+
+ Note that assoc_key_exists was necessary to determine whether or not a
+ word was already added to the array in order to properly initialize
+ it. However, by creating the associative array with a default value
+ of 0, the above code may be simplified to
+
+
+ variable a, word;
+ a = Assoc_Type [Integer_Type, 0];
+ foreach (word_list)
+ {
+ word = ();
+ a[word]++;
+ }
+
+
+
+ 13. Structures and User-Defined Types
+
+
+
+ A structure is a heterogeneous container object, i.e., it is an object
+ with elements whose values do not have to be of the same data type.
+ The elements or fields of a structure are named, and one accesses a
+ particular field of the structure via the field name. This should be
+ contrasted with an array whose values are of the same type, and whose
+ elements are accessed via array indices.
+
+ A user-defined data type is a structure with a fixed set of fields
+ defined by the user.
+
+
+ 13.1. Defining a Structure
+
+
+ The struct keyword is used to define a structure. The syntax for this
+ operation is:
+
+ struct {field-name-1, field-name-2, ... field-name-N};
+
+
+ This creates and returns a structure with N fields whose names are
+ specified by field-name-1, field-name-2, ..., field-name-N. When a
+ structure is created, all its fields are initialized to NULL.
+
+ For example,
+
+
+ variable t = struct { city_name, population, next };
+
+
+
+ creates a structure with three fields and assigns it to the variable
+ t.
+
+ Alternatively, a structure may be created by dereferencing
+ Struct_Type. For example, the above structure may also be created
+ using one of the two forms:
+
+
+ t = @Struct_Type ("city_name", "population", "next");
+ t = @Struct_Type (["city_name", "population", "next"]);
+
+
+
+ These are useful when creating structures dynamically where one does
+ not know the name of the fields until run-time.
+
+ Like arrays, structures are passed around via a references. Thus, in
+ the above example, the value of t is a reference to the structure.
+ This means that after execution of
+
+
+ variable u = t;
+
+
+
+ both t and u refer to the same structure, since only the reference was
+ used in the assignment. To actually create a new copy of the struc-
+ ture, use the dereference operator, e.g.,
+ variable u = @t;
+
+
+
+ 13.2. Accessing the Fields of a Structure
+
+
+ The dot (.) operator is used to specify the particular field of
+ structure. If s is a structure and field_name is a field of the
+ structure, then s.field_name specifies that field of s. This
+ specification can be used in expressions just like ordinary variables.
+ Again, consider
+
+
+ variable t = struct { city_name, population, next };
+
+
+
+ described in the last section. Then,
+
+
+ t.city_name = "New York";
+ t.population = 13000000;
+ if (t.population > 200) t = t.next;
+
+
+
+ are all valid statements involving the fields of t.
+
+
+ 13.3. Linked Lists
+
+
+ One of the most important uses of structures is to create a dynamic
+ data structure such as a linked-list. A linked-list is simply a chain
+ of structures that are linked together such that one structure in the
+ chain is the value of a field of the previous structure in the chain.
+ To be concrete, consider the structure discussed earlier:
+
+
+ variable t = struct { city_name, population, next };
+
+
+
+ and suppose that we desire to create a list of such structures. The
+ purpose of the next field is to provide the link to the next structure
+ in the chain. Suppose that there exists a function, read_next_city,
+ that reads city names and populations from a file. Then we can create
+ the list via:
+
+
+
+ define create_population_list ()
+ {
+ variable city_name, population, list_root, list_tail;
+ variable next;
+
+ list_root = NULL;
+ while (read_next_city (&city_name, &population))
+ {
+ next = struct {city_name, population, next };
+
+ next.city_name = city_name;
+ next.population = population;
+ next.next = NULL;
+
+ if (list_root == NULL)
+ list_root = next;
+ else
+ list_tail.next = next;
+
+ list_tail = next;
+ }
+ return list_root;
+ }
+
+
+
+ In this function, the variables list_root and list_tail represent the
+ beginning and end of the list, respectively. As long as read_next_city
+ returns a non-zero value, a new structure is created, initialized, and
+ then appended to the list via the next field of the list_tail struc-
+ ture. On the first time through the loop, the list is created via the
+ assignment to the list_root variable.
+
+ This function may be used as follows:
+
+
+ variable Population_List = create_population_list ();
+ if (Population_List == NULL) error ("List is empty");
+
+
+
+ We can create other functions that manipulate the list. An example is
+ a function that finds the city with the largest population:
+
+
+ define get_largest_city (list)
+ {
+ variable largest;
+
+ largest = list;
+ while (list != NULL)
+ {
+ if (list.population > largest.population)
+ largest = list;
+ list = list.next;
+ }
+ return largest.city_name;
+ }
+
+ vmessage ("%s is the largest city in the list",
+ get_largest_city (Population_List)));
+
+
+
+ The get_largest_city is a typical example of how one traverses a lin-
+ ear linked-list by starting at the head of the list and successively
+ moves to the next element of the list via the next field.
+
+ In the previous example, a while loop was used to traverse the linked
+ list. It is faster to use a foreach loop for this:
+
+
+ define get_largest_city (list)
+ {
+ variable largest, elem;
+
+ largest = list;
+ foreach (list)
+ {
+ elem = ();
+ if (item.population > largest.population)
+ largest = item;
+ }
+ return largest.city_name;
+ }
+
+
+
+ Here a foreach loop has been used to walk the list via its next field.
+ If the field name was not next, then it would have been necessary to
+ use the using form of the foreach statement. For example, if the
+ field name implementing the linked list was next_item, then
+
+
+ foreach (list) using ("next_item")
+ {
+ elem = ();
+ .
+ .
+ }
+
+
+
+ would have been used. In other words, unless otherwise indicated via
+ the using clause, foreach walks the list using a field named next.
+
+ Now consider a function that sorts the list according to population.
+ To illustrate the technique, a bubble-sort will be used, not because
+ it is efficient, it is not, but because it is simple and intuitive.
+
+
+
+ define sort_population_list (list)
+ {
+ variable changed;
+ variable node, next_node, last_node;
+ do
+ {
+ changed = 0;
+ node = list;
+ next_node = node.next;
+ last_node = NULL;
+ while (next_node != NULL)
+ {
+ if (node.population < next_node.population)
+ {
+ % swap node and next_node
+ node.next = next_node.next;
+ next_node.next = node;
+ if (last_node != NULL)
+ last_node.next = next_node;
+
+ if (list == node) list = next_node;
+ node = next_node;
+ next_node = node.next;
+ changed++;
+ }
+ last_node = node;
+ node = next_node;
+ next_node = next_node.next;
+ }
+ }
+ while (changed);
+
+ return list;
+ }
+
+
+
+ Note the test for equality between list and node, i.e.,
+
+
+ if (list == node) list = next_node;
+
+
+
+ It is important to appreciate the fact that the values of these vari-
+ ables are references to structures, and that the comparison only com-
+ pares the references and not the actual structures they reference. If
+ it were not for this, the algorithm would fail.
+
+
+ 13.4. Defining New Types
+
+
+ A user-defined data type may be defined using the typedef keyword. In
+ the current implementation, a user-defined data type is essentially a
+ structure with a user-defined set of fields. For example, in the
+ previous section a structure was used to represent a city/population
+ pair. We can define a data type called Population_Type to represent
+ the same information:
+
+
+
+ typedef struct
+ {
+ city_name,
+ population
+ } Population_Type;
+
+
+
+ This data type can be used like all other data types. For example, an
+ array of Population_Type types can be created,
+
+
+ variable a = Population_Type[10];
+
+
+
+ and `populated' via expressions such as
+
+
+ a[0].city_name = "Boston";
+ a[0].population = 2500000;
+
+
+
+ The new type Population_Type may also be used with the typeof func-
+ tion:
+
+
+ if (Population_Type = typeof (a)) city = a.city_name;
+
+
+
+ The dereference @ may be used to create an instance of the new type:
+
+
+ a = @Population_Type;
+ a.city_name = "Calcutta";
+ a.population = 13000000;
+
+
+
+ 14. Error Handling
+
+
+
+ Many intrinsic functions signal errors in the event of failure. User
+ defined functions may also generate an error condition via the error
+ function. Depending upon the severity of the error, it can be caught
+ and cleared using a construct called an error-block.
+
+
+ 14.1. Error-Blocks
+
+
+ When the interpreter encounters a recoverable run-time error, it will
+ return to top-level by unwinding its function call stack. Any error-
+ blocks that it encounters as part of this unwinding process will get
+ executed. Errors such as syntax errors and memory allocation errors
+ are not recoverable, and error-blocks will not get executed when such
+ errors are encountered.
+
+ An error-block is defined using the syntax
+
+
+ ERROR_BLOCK { statement-list }
+
+
+
+ where statement-list represents a list of statements that comprise the
+ error-block. A simple example of an error-block is
+
+
+ define simple (a)
+ {
+ ERROR_BLOCK { message ("error-block executed"); }
+ if (a) error ("Triggering Error");
+ message ("hello");
+ }
+
+
+
+ Executing this function via simple(0) will result in the message
+ "hello". However, calling it using simple(1) will generate an error
+ that will be caught, but not cleared, by the error-block and the
+ "error-block executed" message will result.
+
+ Error-blocks are never executed unless triggered by an error. The
+ only exception to this is when the user explicitly indicates that the
+ error-block in scope should execute. This is indicated by the special
+ keyword EXECUTE_ERROR_BLOCK. For example, simple could be recoded as
+
+
+ define simple (a)
+ {
+ variable err_string = "error-block executed";
+ ERROR_BLOCK { message (err_string); }
+ if (a) error ("Triggering Error");
+ err_string = "hello";
+ EXECUTE_ERROR_BLOCK;
+ }
+
+
+
+ Please note that EXECUTE_ERROR_BLOCK does not initiate an error
+ condition; it simply causes the error-block to be executed and control
+ will pass onto the next statement following the EXECUTE_ERROR_BLOCK
+ statement.
+
+
+ 14.2. Clearing Errors
+
+
+ Once an error has been caught by an error-block, the error can be
+ cleared by the _clear_error function. After the error has been
+ cleared, execution will resume at the next statement at the level of
+ the error block following the statement that generated the error. For
+ example, consider:
+
+
+ define make_error ()
+ {
+ error ("Error condition created.");
+ message ("This statement is not executed.");
+ }
+
+ define test ()
+ {
+ ERROR_BLOCK
+ {
+ _clear_error ();
+ }
+ make_error ();
+ message ("error cleared.");
+ }
+
+
+
+ Calling test will trigger an error in the make_error function, but
+ will get cleared in the test function. The call-stack will unwind
+ from make_error back into test where the error-block will get exe-
+ cuted. As a result, execution resumes after the statement that makes
+ the call to make_error since this statement is at the same level as
+ the error-block that cleared the error.
+
+ Here is another example that illustrates how multiple error-blocks
+ work:
+
+
+
+ define example ()
+ {
+ variable n = 0, s = "";
+ variable str;
+
+ ERROR_BLOCK {
+ str = sprintf ("s=%s,n=%d", s, n);
+ _clear_error ();
+ }
+
+ forever
+ {
+ ERROR_BLOCK {
+ s += "0";
+ _clear_error ();
+ }
+
+ if (n == 0) error ("");
+
+ ERROR_BLOCK {
+ s += "1";
+ }
+
+ if (n == 1) error ("");
+ n++;
+ }
+ return str;
+ }
+
+
+
+ Here, three error-blocks have been declared. One has been declared
+ outside the forever loop and the other two have been declared inside
+ the forever loop. Each time through the loop, the variable n is
+ incremented and a different error-block is triggered. The error-block
+ that gets triggered is the last one encountered, since that will be
+ the one in scope. On the first time through the loop, n will be zero
+ and the first error-block in the loop will get executed. This error
+ block clears the error and execution resumes following the if state-
+ ment that triggered the error. The variable n will get incremented to
+ 1 and, on the second cycle through the loop the second if statement
+ will trigger an error causing the second error-block to execute. This
+ time, the error is not cleared and the call-stack unwinds out of the
+ forever loop, at which point the error-block outside the loop is in
+ scope, causing it to execute. This error-block prints out the values
+ of the variables s and n. It will clear the error and execution
+ resumes on the statement following the forever loop. The result of
+ this complicated series of events is that the function will return the
+ string "s=01,n=1".
+
+
+
+ 15. Loading Files: evalfile and autoload
+
+
+
+ 16. File Input/Output
+
+
+
+ S-Lang provides built-in supports for two different I/O facilities.
+ The simplest interface is modeled upon the C language stdio streams
+ interface and consists of functions such as fopen, fgets, etc. The
+ other interface is modeled on a lower level POSIX interface consisting
+ of functions such as open, read, etc. In addition to permitting more
+ control, the lower level interface permits one to access network
+ objects as well as disk files.
+
+
+ 16.1. Input/Output via stdio
+
+
+ 16.1.1. Stdio Overview
+
+ The stdio interface consists of the following functions:
+
+ o fopen, which opens a file for read or writing.
+
+ o fclose, which closes a file opened by fopen.
+
+ o fgets, used to read a line from the file.
+
+ o fputs, which writes text to the file.
+
+ o fprintf, used to write formatted text to the file.
+
+ o fwrite, which may be used to write objects to the file.
+
+ o fread, which reads a specified number of objects from the file.
+
+ o feof, which is used to test whether the file pointer is at the end
+ of the file.
+
+ o ferror, which is used to see whether or not the stream associated
+ with the file has an error.
+
+
+ o clearerr, which clears the end-of-file and error indicators for the
+ stream.
+
+ o fflush, used to force all buffered data associated with the stream
+ to be written out.
+
+ o ftell, which is used to query the file position indicator of the
+ stream.
+
+
+ o fseek, which is used to set the position of the file position
+ indicator of the stream.
+
+ o fgetslines, which reads all the lines in a text file and returns
+ them as an array of strings.
+
+ In addition, the interface supports the popen and pclose functions on
+ systems where the corresponding C functions are available.
+
+ Before reading or writing to a file, it must first be opened using the
+ fopen function. The only exceptions to this rule involves use of the
+ pre-opened streams: stdin, stdout, and stderr. fopen accepts two
+ arguments: a file name and a string argument that indicates how the
+ file is to be opened, e.g., for reading, writing, update, etc. It
+ returns a File_Type stream object that is used as an argument to all
+ other functions of the stdio interface. Upon failure, it returns
+ NULL. See the reference manual for more information about fopen.
+
+
+ 16.1.2. Stdio Examples
+
+
+ In this section, some simple examples of the use of the stdio
+ interface is presented. It is important to realize that all the
+ functions of the interface return something, and that return value
+ must be dealt with.
+
+ The first example involves writing a function to count the number of
+ lines in a text file. To do this, we shall read in the lines, one by
+ one, and count them:
+
+
+ define count_lines_in_file (file)
+ {
+ variable fp, line, count;
+
+ fp = fopen (file, "r"); % Open the file for reading
+ if (fp == NULL)
+ verror ("%s failed to open", file);
+
+ count = 0;
+ while (-1 != fgets (&line, fp))
+ count++;
+
+ () = fclose (fp);
+ return count;
+ }
+
+
+
+ Note that &line was passed to the fgets function. When fgets returns,
+ line will contain the line of text read in from the file. Also note
+ how the return value from fclose was handled.
+
+ Although the preceding example closed the file via fclose, there is no
+ need to explicitly close a file because S-Lang will automatically
+ close the file when it is no longer referenced. Since the only
+ variable to reference the file is fp, it would have automatically been
+ closed when the function returned.
+
+ Suppose that it is desired to count the number of characters in the
+ file instead of the number of lines. To do this, the while loop could
+ be modified to count the characters as follows:
+
+
+ while (-1 != fgets (&line, fp))
+ count += strlen (line);
+
+
+
+ The main difficulty with this approach is that it will not work for
+ binary files, i.e., files that contain null characters. For such
+ files, the file should be opened in binary mode via
+
+
+ fp = fopen (file, "rb");
+
+
+
+ and then the data read in using the fread function:
+
+
+ while (-1 != fread (&line, Char_Type, 1024, fp))
+ count += bstrlen (line);
+
+
+
+ The fread function requires two additional arguments: the type of
+ object to read (Char_Type in the case), and the number of such objects
+ to read. The function returns the number of objects actually read, or
+ -1 upon failure. The bstrlen function was used to compute the length
+ of line because for Char_Type or UChar_Type objects, the fread func-
+ tion assigns a binary string (BString_Type) to line.
+
+ The foreach construct also works with File_Type objects. For example,
+ the number of characters in a file may be counted via
+
+
+ foreach (fp) using ("char")
+ {
+ ch = ();
+ count++;
+ }
+
+
+
+ To count the number of lines, one can use:
+
+
+ foreach (fp) using ("line")
+ {
+ line = ();
+ num_lines++;
+ count += strlen (line);
+ }
+
+
+
+ Often one is not interested in trailing whitespace in the lines of a
+ file. To have trailing whitespace automatically stripped from the
+ lines as they are read in, use the "wsline" form, e.g.,
+
+
+ foreach (fp) using ("wsline")
+ {
+ line = ();
+ .
+ .
+ }
+
+
+
+ Finally, it should be mentioned that none of these examples should be
+ used to count the number of bytes in a file when that information is
+ more readily accessible by another means. For example, it is
+ preferable to get this information via the stat_file function:
+
+
+
+ define count_chars_in_file (file)
+ {
+ variable st;
+
+ st = stat_file (file);
+ if (st == NULL)
+ error ("stat_file failed.");
+ return st.st_size;
+ }
+
+
+
+ 16.2. POSIX I/O
+
+
+
+ 16.3. Advanced I/O techniques
+
+
+ The previous examples illustrate how to read and write objects of a
+ single data-type from a file, e.g.,
+
+
+ num = fread (&a, Double_Type, 20, fp);
+
+
+
+ would result in a Double_Type[num] array being assigned to a if suc-
+ cessful. However, suppose that the binary data file consists of num-
+ bers in a specified byte-order. How can one read such objects with
+ the proper byte swapping? The answer is to use the fread function to
+ read the objects as Char_Type and then unpack the resulting string
+ into the specified data type, or types. This process is facilitated
+ using the pack and unpack functions.
+
+ The pack function follows the syntax
+
+ BString_Type pack (format-string, item-list);
+
+
+ and combines the objects in the item-list according to format-string
+ into a binary string and returns the result. Likewise, the unpack
+ function may be used to convert a binary string into separate data
+ objects:
+
+ (variable-list) = unpack (format-string, binary-string);
+
+
+ The format string consists of one or more data-type specification
+ characters, and each may be followed by an optional decimal length
+ specifier. Specifically, the data-types are specified according to the
+ following table:
+
+
+
+ c char
+ C unsigned char
+ h short
+ H unsigned short
+ i int
+ I unsigned int
+ l long
+ L unsigned long
+ j 16 bit int
+ J 16 unsigned int
+ k 32 bit int
+ K 32 bit unsigned int
+ f float
+ d double
+ F 32 bit float
+ D 64 bit float
+ s character string, null padded
+ S character string, space padded
+ x a null pad character
+
+
+
+ A decimal length specifier may follow the data-type specifier. With
+ the exception of the s and S specifiers, the length specifier indi-
+ cates how many objects of that data type are to be packed or unpacked
+ from the string. When used with the s or S specifiers, it indicates
+ the field width to be used. If the length specifier is not present,
+ the length defaults to one.
+
+ With the exception of c, C, s, S, and x, each of these may be prefixed
+ by a character that indicates the byte-order of the object:
+
+
+ > big-endian order (network order)
+ < little-endian order
+ = native byte-order
+
+
+
+ The default is native byte order.
+
+ Here are a few examples that should make this more clear:
+
+
+ a = pack ("cc", 'A', 'B'); % ==> a = "AB";
+ a = pack ("c2", 'A', 'B'); % ==> a = "AB";
+ a = pack ("xxcxxc", 'A', 'B'); % ==> a = "\0\0A\0\0B";
+ a = pack ("h2", 'A', 'B'); % ==> a = "\0A\0B" or "\0B\0A"
+ a = pack (">h2", 'A', 'B'); % ==> a = "\0\xA\0\xB"
+ a = pack ("<h2", 'A', 'B'); % ==> a = "\0B\0A"
+ a = pack ("s4", "AB", "CD"); % ==> a = "AB\0\0"
+ a = pack ("s4s2", "AB", "CD"); % ==> a = "AB\0\0CD"
+ a = pack ("S4", "AB", "CD"); % ==> a = "AB "
+ a = pack ("S4S2", "AB", "CD"); % ==> a = "AB CD"
+
+
+
+ When unpacking, if the length specifier is greater than one, then an
+ array of that length will be returned. In addition, trailing
+ whitespace and null character are stripped when unpacking an object
+ given by the S specifier. Here are a few examples:
+
+
+ (x,y) = unpack ("cc", "AB"); % ==> x = 'A', y = 'B'
+ x = unpack ("c2", "AB"); % ==> x = ['A', 'B']
+ x = unpack ("x<H", "\0\xAB\xCD"); % ==> x = 0xCDABuh
+ x = unpack ("xxs4", "a b c\0d e f"); % ==> x = "b c\0"
+ x = unpack ("xxS4", "a b c\0d e f"); % ==> x = "b c"
+
+
+
+ 16.3.1. Example: Reading /var/log/wtmp
+
+
+ Consider the task of reading the Unix system file /var/log/utmp, which
+ contains login records about who logged onto the system. This file
+ format is documented in section 5 of the online Unix man pages, and
+ consists of a sequence of entries formatted according to the C
+ structure utmp defined in the utmp.h C header file. The actual
+ details of the structure may vary from one version of Unix to the
+ other. For the purposes of this example, consider its definition
+ under the Linux operating system running on an Intel processor:
+
+
+ struct utmp {
+ short ut_type; /* type of login */
+ pid_t ut_pid; /* pid of process */
+ char ut_line[12]; /* device name of tty - "/dev/" */
+ char ut_id[2]; /* init id or abbrev. ttyname */
+ time_t ut_time; /* login time */
+ char ut_user[8]; /* user name */
+ char ut_host[16]; /* host name for remote login */
+ long ut_addr; /* IP addr of remote host */
+ };
+
+
+
+ On this system, pid_t is defined to be an int and time_t is a long.
+ Hence, a format specifier for the pack and unpack functions is easily
+ constructed to be:
+
+
+ "h i S12 S2 l S8 S16 l"
+
+
+
+ However, this particular definition is naive because it does not allow
+ for structure padding performed by the C compiler in order to align
+ the data types on suitable word boundaries. Fortunately, the intrin-
+ sic function pad_pack_format may be used to modify a format by adding
+ the correct amount of padding in the right places. In fact,
+ pad_pack_format applied to the above format on an Intel-based Linux
+ system produces the result:
+
+
+ "h x2 i S12 S2 x2 l S8 S16 l"
+
+
+
+ Here we see that 4 bytes of padding were added.
+
+ The other missing piece of information is the size of the structure.
+ This is useful because we would like to read in one structure at a
+ time using the fread function. Knowing the size of the various data
+ types makes this easy; however it is even easier to use the
+ sizeof_pack intrinsic function, which returns the size (in bytes) of
+ the structure described by the pack format.
+
+ So, with all the pieces in place, it is rather straightforward to
+ write the code:
+
+
+ variable format, size, fp, buf;
+
+ typedef struct
+ {
+ ut_type, ut_pid, ut_line, ut_id,
+ ut_time, ut_user, ut_host, ut_addr
+ } UTMP_Type;
+
+ format = pad_pack_format ("h i S12 S2 l S8 S16 l");
+ size = sizeof_pack (format);
+
+ define print_utmp (u)
+ {
+
+ () = fprintf (stdout, "%-16s %-12s %-16s %s\n",
+ u.ut_user, u.ut_line, u.ut_host, ctime (u.ut_time));
+ }
+
+
+ fp = fopen ("/var/log/utmp", "rb");
+ if (fp == NULL)
+ error ("Unable to open utmp file");
+
+ () = fprintf (stdout, "%-16s %-12s %-16s %s\n",
+ "USER", "TTY", "FROM", "LOGIN@");
+
+ variable U = @UTMP_Type;
+
+ while (-1 != fread (&buf, Char_Type, size, fp))
+ {
+ set_struct_fields (U, unpack (format, buf));
+ print_utmp (U);
+ }
+
+ () = fclose (fp);
+
+
+
+ A few comments about this example are in order. First of all, note
+ that a new data type called UTMP_Type was created, although this was
+ not really necessary. We also opened the file in binary mode, but
+ this too is optional under a Unix system where there is no distinction
+ between binary and text modes. The print_utmp function does not print
+ all of the structure fields. Finally, last but not least, the return
+ values from fprintf and fclose were dealt with.
+
+
+
+ 17. Debugging
+
+
+
+ The current implementation provides no support for an interactive
+ debugger, although a future version will. Nevertheless, S-Lang has
+ several features that aid the programmer in tracking down problems,
+ including function call tracebacks and the tracing of function calls.
+ However, the biggest debugging aid stems from the fact that the
+ language is interpreted permitting one to easily add debugging
+ statements to the code.
+
+ To enable debugging information, add the lines
+
+
+ _debug_info = 1;
+ _traceback = 1;
+
+
+
+ to the top of the source file of the code containing the bug and the
+ reload the file. Setting the _debug_info variable to 1 causes line
+ number information to be compiled into the functions when the file is
+ loaded. The _traceback variable controls whether or not traceback
+ information should be generated. If it is set to 1, the values of
+ local variables will be dumped when the traceback is generated. Set-
+ ting this variable to -1 will cause only function names to be reported
+ in the traceback.
+
+ Here is an example of a traceback report:
+
+
+ S-Lang Traceback: error
+ S-Lang Traceback: verror
+ S-Lang Traceback: (Error occurred on line 65)
+ S-Lang Traceback: search_generic_search
+ Local Variables:
+ $0: Type: String_Type, Value: "Search forward:"
+ $1: Type: Integer_Type, Value: 1
+ $2: Type: Ref_Type, Value: _function_return_1
+ $3: Type: String_Type, Value: "abcdefg"
+ $4: Type: Integer_Type, Value: 1
+ S-Lang Traceback: (Error occurred on line 72)
+ S-Lang Traceback: search_forward
+
+
+
+ There are several ways to read this report; perhaps the simplest is to
+ read it from the bottom. This report says that on line 72, the
+ search_forward function called the search_generic_search function. On
+ line 65 it called the verror function, which called error. The
+ search_generic_search function contains 5 local variables and are rep-
+ resented symbolically as $0 through $4.
+
+
+
+ 18. Regular Expressions
+
+
+ The S-Lang library includes a regular expression (RE) package that may
+ be used by an application embedding the library. The RE syntax should
+ be familiar to anyone acquainted with regular expressions. In this
+ section the syntax of the S-Lang regular expressions is discussed.
+
+
+ 18.1. S-Lang RE Syntax
+
+
+ A regular expression specifies a pattern to be matched against a
+ string, and has the property that the contcatenation of two REs is
+ also a RE.
+
+ The S-Lang library supports the following standard regular
+ expressions:
+
+
+ . match any character except newline
+ * matches zero or more occurences of previous RE
+ + matches one or more occurences of previous RE
+ ? matches zero or one occurence of previous RE
+ ^ matches beginning of a line
+ $ matches end of line
+ [ ... ] matches any single character between brackets.
+ For example, [-02468] matches `-' or any even digit.
+ and [-0-9a-z] matches `-' and any digit between 0 and 9
+ as well as letters a through z.
+ \< Match the beginning of a word.
+ \> Match the end of a word.
+ \( ... \)
+ \1, \2, ..., \9 Matches the match specified by nth \( ... \)
+ expression.
+
+
+
+ In addition the following extensions are also supported:
+
+
+ \c turn on case-sensitivity (default)
+ \C turn off case-sensitivity
+ \d match any digit
+ \e match ESC char
+
+
+
+ Here are some simple examples:
+
+ "^int " matches the "int " at the beginning of a line.
+
+ "\<money\>" matches "money" but only if it appears as a separate word.
+
+ "^$" matches an empty line.
+
+ A more complex pattern is
+
+
+ "\(\<[a-zA-Z]+\>\)[ ]+\1\>"
+
+
+
+ which matches any word repeated consecutively. Note how the grouping
+ operators \( and \) are used to define the text matched by the
+ enclosed regular expression, and then subsequently referred to \1.
+
+ Finally, remember that when used in string literals either in the S-
+ Lang language or in the C language, care must be taken to "double-up"
+ the '\' character since both languages treat it as an escape
+ character.
+
+
+ 18.2. Differences between S-Lang and egrep REs
+
+
+ There are several differences between S-Lang regular expressions and,
+ e.g., egrep regular expressions.
+
+ The most notable difference is that the S-Lang regular expressions do
+ not support the OR operator | in expressions. This means that "a|b"
+ or "a\|b" do not have the meaning that they have in regular expression
+ packages that support egrep-style expressions.
+
+ The other main difference is that while S-Lang regular expressions
+ support the grouping operators \( and \), they are only used as a
+ means of specifying the text that is matched. That is, the expression
+
+
+ "@\([a-z]*\)@.*@\1@"
+
+
+
+ matches "xxx@abc@silly@abc@yyy", where the pattern \1 matches the text
+ enclosed by the \( and \) expressions. However, in the current imple-
+ mentation, the grouping operators are not used to group regular
+ expressions to form a single regular expression. Thus expression such
+ as "\(hello\)*" is not a pattern to match zero or more occurances of
+ "hello" as it is in e.g., egrep.
+
+ One question that comes up from time to time is why doesn't S-Lang
+ simply employ some posix-compatible regular expression library. The
+ simple answer is that, at the time of this writing, none exists that
+ is available across all the platforms that the S-Lang library supports
+ (Unix, VMS, OS/2, win32, win16, BEOS, MSDOS, and QNX) and can be
+ distributed under both the GNU and Artistic licenses. It is
+ particularly important that the library and the interpreter support a
+ common set of regular expressions in a platform independent manner.
+
+
+
+ 19. Future Directions
+
+
+
+ Several new features or enhancements to the S-Lang language are
+ planned for the next major release. In no particular order, these
+ include:
+
+ o An interactive debugging facility.
+
+ o Function qualifiers. These entities should already be familiar to
+ VMS users or to those who are familiar with the IDL language.
+ Basically, a qualifier is an optional argument that is passed to a
+ function, e.g., plot(X,Y,/logx). Here /logx is a qualifier that
+ specifies that the plot function should use a log scale for x.
+
+ o File local variables and functions. A file local variable or
+ function is an object that is global to the file that defines it.
+
+ o Multi-threading. Currently the language does not support multiple
+ threads.
+
+
+
+ A. Copyright
+
+ The S-Lang library is distributed under two copyrights: the GNU Genral
+ Public License, and the Artistic License. Any program that uses the
+ interpreter must adhere to rules of one of these licenses.
+
+
+ A.1. The GNU Public License
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+
+
+ The licenses for most software are designed to take away your freedom
+ to share and change it. By contrast, the GNU General Public License
+ is intended to guarantee your freedom to share and change free soft-
+ ware--to make sure the software is free for all its users. This Gen-
+ eral Public License applies to most of the Free Software Foundation's
+ software and to any other program whose authors commit to using it.
+ (Some other Free Software Foundation software is covered by the GNU
+ Library General Public License instead.) You can apply it to your
+ programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+ price. Our General Public Licenses are designed to make sure that you
+ have the freedom to distribute copies of free software (and charge for
+ this service if you wish), that you receive source code or can get it
+ if you want it, that you can change the software or use pieces of it
+ in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+ anyone to deny you these rights or to ask you to surrender the rights.
+ These restrictions translate to certain responsibilities for you if
+ you distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+ gratis or for a fee, you must give the recipients all the rights that
+ you have. You must make sure that they, too, receive or can get the
+ source code. And you must show them these terms so they know their
+ rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+ (2) offer you this license which gives you legal permission to copy,
+ distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+ that everyone understands that there is no warranty for this free
+ software. If the software is modified by someone else and passed on,
+ we want its recipients to know that what they have is not the
+ original, so that any problems introduced by others will not reflect
+ on the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+ patents. We wish to avoid the danger that redistributors of a free
+ program will individually obtain patent licenses, in effect making the
+ program proprietary. To prevent this, we have made it clear that any
+ patent must be licensed for everyone's free use or not licensed at
+ all.
+
+ The precise terms and conditions for copying, distribution and
+ modification follow.
+
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+
+
+ 0. This License applies to any program or other work which contains a
+ notice placed by the copyright holder saying it may be distributed
+ under the terms of this General Public License. The "Program", below,
+ refers to any such program or work, and a "work based on the Program"
+ means either the Program or any derivative work under copyright law:
+ that is to say, a work containing the Program or a portion of it,
+ either verbatim or with modifications and/or translated into another
+ language. (Hereinafter, translation is included without limitation in
+ the term "modification".) Each licensee is addressed as "you".
+
+ Activities other than copying, distribution and modification are not
+ covered by this License; they are outside its scope. The act of
+ running the Program is not restricted, and the output from the Program
+ is covered only if its contents constitute a work based on the Program
+ (independent of having been made by running the Program). Whether
+ that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+ code as you receive it, in any medium, provided that you conspicuously
+ and appropriately publish on each copy an appropriate copyright notice
+ and disclaimer of warranty; keep intact all the notices that refer to
+ this License and to the absence of any warranty; and give any other
+ recipients of the Program a copy of this License along with the
+ Program.
+
+ You may charge a fee for the physical act of transferring a copy, and
+ you may at your option offer warranty protection in exchange for a
+ fee.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+ it, thus forming a work based on the Program, and copy and distribute
+ such modifications or work under the terms of Section 1 above,
+ provided that you also meet all of these conditions:
+
+
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+
+
+ These requirements apply to the modified work as a whole. If identi-
+ fiable sections of that work are not derived from the Program, and can
+ be reasonably considered independent and separate works in themselves,
+ then this License, and its terms, do not apply to those sections when
+ you distribute them as separate works. But when you distribute the
+ same sections as part of a whole which is a work based on the Program,
+ the distribution of the whole must be on the terms of this License,
+ whose permissions for other licensees extend to the entire whole, and
+ thus to each and every part regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or contest
+ your rights to work written entirely by you; rather, the intent is to
+ exercise the right to control the distribution of derivative or
+ collective works based on the Program.
+
+ In addition, mere aggregation of another work not based on the Program
+ with the Program (or with a work based on the Program) on a volume of
+ a storage or distribution medium does not bring the other work under
+ the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+ under Section 2) in object code or executable form under the terms of
+ Sections 1 and 2 above provided that you also do one of the following:
+
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+
+
+ The source code for a work means the preferred form of the work for
+ making modifications to it. For an executable work, complete source
+ code means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to con-
+ trol compilation and installation of the executable. However, as a
+ special exception, the source code distributed need not include any-
+ thing that is normally distributed (in either source or binary form)
+ with the major components (compiler, kernel, and so on) of the operat-
+ ing system on which the executable runs, unless that component itself
+ accompanies the executable.
+
+ If distribution of executable or object code is made by offering
+ access to copy from a designated place, then offering equivalent
+ access to copy the source code from the same place counts as
+ distribution of the source code, even though third parties are not
+ compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+ except as expressly provided under this License. Any attempt
+ otherwise to copy, modify, sublicense or distribute the Program is
+ void, and will automatically terminate your rights under this License.
+ However, parties who have received copies, or rights, from you under
+ this License will not have their licenses terminated so long as such
+ parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify or
+ distribute the Program or its derivative works. These actions are
+ prohibited by law if you do not accept this License. Therefore, by
+ modifying or distributing the Program (or any work based on the
+ Program), you indicate your acceptance of this License to do so, and
+ all its terms and conditions for copying, distributing or modifying
+ the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+ Program), the recipient automatically receives a license from the
+ original licensor to copy, distribute or modify the Program subject to
+ these terms and conditions. You may not impose any further
+ restrictions on the recipients' exercise of the rights granted herein.
+ You are not responsible for enforcing compliance by third parties to
+ this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent issues),
+ conditions are imposed on you (whether by court order, agreement or
+ otherwise) that contradict the conditions of this License, they do not
+ excuse you from the conditions of this License. If you cannot
+ distribute so as to satisfy simultaneously your obligations under this
+ License and any other pertinent obligations, then as a consequence you
+ may not distribute the Program at all. For example, if a patent
+ license would not permit royalty-free redistribution of the Program by
+ all those who receive copies directly or indirectly through you, then
+ the only way you could satisfy both it and this License would be to
+ refrain entirely from distribution of the Program.
+
+ If any portion of this section is held invalid or unenforceable under
+ any particular circumstance, the balance of the section is intended to
+ apply and the section as a whole is intended to apply in other
+ circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of any
+ such claims; this section has the sole purpose of protecting the
+ integrity of the free software distribution system, which is
+ implemented by public license practices. Many people have made
+ generous contributions to the wide range of software distributed
+ through that system in reliance on consistent application of that
+ system; it is up to the author/donor to decide if he or she is willing
+ to distribute software through any other system and a licensee cannot
+ impose that choice.
+
+ This section is intended to make thoroughly clear what is believed to
+ be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+ certain countries either by patents or by copyrighted interfaces, the
+ original copyright holder who places the Program under this License
+ may add an explicit geographical distribution limitation excluding
+ those countries, so that distribution is permitted only in or among
+ countries not thus excluded. In such case, this License incorporates
+ the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new
+ versions of the General Public License from time to time. Such new
+ versions will be similar in spirit to the present version, but may
+ differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the Program
+ specifies a version number of this License which applies to it and
+ "any later version", you have the option of following the terms and
+ conditions either of that version or of any later version published by
+ the Free Software Foundation. If the Program does not specify a
+ version number of this License, you may choose any version ever
+ published by the Free Software Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+ programs whose distribution conditions are different, write to the
+ author to ask for permission. For software which is copyrighted by
+ the Free Software Foundation, write to the Free Software Foundation;
+ we sometimes make exceptions for this. Our decision will be guided by
+ the two goals of preserving the free status of all derivatives of our
+ free software and of promoting the sharing and reuse of software
+ generally.
+
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+ REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+ possible use to the public, the best way to achieve this is to make it
+ free software which everyone can redistribute and change under these
+ terms.
+
+ To do so, attach the following notices to the program. It is safest
+ to attach them to the start of each source file to most effectively
+ convey the exclusion of warranty; and each file should have at least
+ the "copyright" line and a pointer to where the full notice is found.
+
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+
+ Also add information on how to contact you by electronic and paper
+ mail.
+
+ If the program is interactive, make it output a short notice like this
+ when it starts in an interactive mode:
+
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+
+
+ The hypothetical commands `show w' and `show c' should show the appro-
+ priate parts of the General Public License. Of course, the commands
+ you use may be called something other than `show w' and `show c'; they
+ could even be mouse-clicks or menu items--whatever suits your program.
+
+ You should also get your employer (if you work as a programmer) or
+ your school, if any, to sign a "copyright disclaimer" for the program,
+ if necessary. Here is a sample; alter the names:
+
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+
+
+ This General Public License does not permit incorporating your program
+ into proprietary programs. If your program is a subroutine library,
+ you may consider it more useful to permit linking proprietary applica-
+ tions with the library. If this is what you want to do, use the GNU
+ Library General Public License instead of this License.
+
+
+ A.2. The Artistic License
+
+
+
+ The "Artistic License"
+
+ Preamble
+
+
+
+ The intent of this document is to state the conditions under which a
+ Package may be copied, such that the Copyright Holder maintains some
+ semblance of artistic control over the development of the package,
+ while giving the users of the package the right to use and distribute
+ the Package in a more-or-less customary fashion, plus the right to
+ make reasonable modifications.
+
+ Definitions:
+
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+
+
+
+ 1. You may make and give away verbatim copies of the source form of
+ the Standard Version of this Package without restriction, provided
+ that you duplicate all of the original copyright notices and associ-
+ ated disclaimers.
+
+ 2. You may apply bug fixes, portability fixes and other modifications
+ derived from the Public Domain or from the Copyright Holder. A
+ Package modified in such a way shall still be considered the Standard
+ Version.
+
+ 3. You may otherwise modify your copy of this Package in any way,
+ provided that you insert a prominent notice in each changed file
+ stating how and when you changed that file, and provided that you do
+ at least ONE of the following:
+
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+
+
+ 4. You may distribute the programs of this Package in object code or
+ executable form, provided that you do at least ONE of the following:
+
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+
+
+ 5. You may charge a reasonable copying fee for any distribution of
+ this Package. You may charge any fee you choose for support of this
+ Package. You may not charge a fee for this Package itself. However,
+ you may distribute this Package in aggregate with other (possibly com-
+ mercial) programs as part of a larger (possibly commercial) software
+ distribution provided that you do not advertise this Package as a
+ product of your own. You may embed this Package's interpreter within
+ an executable of yours (by linking); this shall be construed as a mere
+ form of aggregation, provided that the complete Standard Version of
+ the interpreter is so embedded.
+
+ 6. The scripts and library files supplied as input to or produced as
+ output from the programs of this Package do not automatically fall
+ under the copyright of this Package, but belong to whomever generated
+ them, and may be sold commercially, and may be aggregated with this
+ Package. If such scripts or library files are aggregated with this
+ Package via the so-called "undump" or "unexec" methods of producing a
+ binary executable image, then distribution of such an image shall
+ neither be construed as a distribution of this Package nor shall it
+ fall under the restrictions of Paragraphs 3 and 4, provided that you
+ do not represent such an executable image as a Standard Version of
+ this Package.
+ 7. C subroutines (or comparably compiled subroutines in other
+ languages) supplied by you and linked into this Package in order to
+ emulate subroutines and variables of the language defined by this
+ Package shall not be considered part of this Package, but are the
+ equivalent of input as in Paragraph 6, provided these subroutines do
+ not change the language in any way that would cause it to fail the
+ regression tests for the language.
+
+ 8. Aggregation of this Package with a commercial distribution is
+ always permitted provided that the use of this Package is embedded;
+ that is, when no overt attempt is made to make this Package's
+ interfaces visible to the end user of the commercial distribution.
+ Such use shall not be construed as a distribution of this Package.
+
+ 9. The name of the Copyright Holder may not be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+ 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+ Table of Contents
+
+
+ 1. Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
+ 1.1. A Brief History of S-Lang . . . . . . . . . . . . . . . . . . 4
+ 1.2. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 4
+ 2. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 6
+ 2.1. Language Features . . . . . . . . . . . . . . . . . . . . . . 6
+ 2.2. Data Types and Operators . . . . . . . . . . . . . . . . . . 6
+ 2.3. Statements and Functions . . . . . . . . . . . . . . . . . . 6
+ 2.4. Error Handling . . . . . . . . . . . . . . . . . . . . . . . 7
+ 2.5. Run-Time Library . . . . . . . . . . . . . . . . . . . . . . 7
+ 2.6. Input/Output . . . . . . . . . . . . . . . . . . . . . . . . 7
+ 2.7. Obtaining S-Lang . . . . . . . . . . . . . . . . . . . . . . 8
+ 3. Overview of the Language . . . . . . . . . . . . . . . . . . . 9
+ 3.1. Variables and Functions . . . . . . . . . . . . . . . . . . . 9
+ 3.2. Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
+ 3.3. Referencing and Dereferencing . . . . . . . . . . . . . . . . 11
+ 3.4. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
+ 3.5. Structures and User-Defined Types . . . . . . . . . . . . . . 15
+ 3.6. Namespaces . . . . . . . . . . . . . . . . . . . . . . . . . 16
+ 4. Data Types and Literal Constants . . . . . . . . . . . . . . . 18
+ 4.1. Predefined Data Types . . . . . . . . . . . . . . . . . . . . 18
+ 4.1.1. Integers . . . . . . . . . . . . . . . . . . . . . . . . . 18
+ 4.1.2. Floating Point Numbers . . . . . . . . . . . . . . . . . . 19
+ 4.1.3. Complex Numbers . . . . . . . . . . . . . . . . . . . . . . 19
+ 4.1.4. Strings . . . . . . . . . . . . . . . . . . . . . . . . . . 20
+ 4.1.5. Null_Type . . . . . . . . . . . . . . . . . . . . . . . . . 21
+ 4.1.6. Ref_Type . . . . . . . . . . . . . . . . . . . . . . . . . 21
+ 4.1.7. Array_Type and Struct_Type . . . . . . . . . . . . . . . . 22
+ 4.1.8. DataType_Type Type . . . . . . . . . . . . . . . . . . . . 22
+ 4.2. Typecasting: Converting from one Type to Another . . . . . . 23
+ 5. Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . 25
+ 6. Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
+ 7. Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
+ 7.1. Unary Operators . . . . . . . . . . . . . . . . . . . . . . . 28
+ 7.2. Binary Operators . . . . . . . . . . . . . . . . . . . . . . 28
+ 7.2.1. Arithmetic Operators . . . . . . . . . . . . . . . . . . . 29
+ 7.2.2. Relational Operators . . . . . . . . . . . . . . . . . . . 29
+ 7.2.3. Boolean Operators . . . . . . . . . . . . . . . . . . . . . 29
+ 7.2.4. Bitwise Operators . . . . . . . . . . . . . . . . . . . . . 30
+ 7.2.5. Namespace operator . . . . . . . . . . . . . . . . . . . . 31
+ 7.2.6. Operator Precedence . . . . . . . . . . . . . . . . . . . . 31
+ 7.2.7. Binary Operators and Functions Returning Multiple Val-
+ ues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
+ 7.3. Mixing Integer and Floating Point Arithmetic . . . . . . . . 32
+ 7.4. Short Circuit Boolean Evaluation . . . . . . . . . . . . . . 33
+ 8. Statements . . . . . . . . . . . . . . . . . . . . . . . . . . 34
+ 8.1. Variable Declaration Statements . . . . . . . . . . . . . . . 34
+ 8.2. Assignment Statements . . . . . . . . . . . . . . . . . . . . 34
+ 8.3. Conditional and Looping Statements . . . . . . . . . . . . . 36
+ 8.3.1. Conditional Forms . . . . . . . . . . . . . . . . . . . . . 36
+ 8.3.1.1. if . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
+ 8.3.1.2. if-else . . . . . . . . . . . . . . . . . . . . . . . . . 36
+ 8.3.1.3. !if . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
+ 8.3.1.4. orelse, andelse . . . . . . . . . . . . . . . . . . . . . 38
+ 8.3.1.5. switch . . . . . . . . . . . . . . . . . . . . . . . . . 38
+ 8.3.2. Looping Forms . . . . . . . . . . . . . . . . . . . . . . . 40
+ 8.3.2.1. while . . . . . . . . . . . . . . . . . . . . . . . . . . 40
+ 8.3.2.2. do...while . . . . . . . . . . . . . . . . . . . . . . . 41
+ 8.3.2.3. for . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
+ 8.3.2.4. loop . . . . . . . . . . . . . . . . . . . . . . . . . . 42
+ 8.3.2.5. loop . . . . . . . . . . . . . . . . . . . . . . . . . . 42
+ 8.3.2.6. forever . . . . . . . . . . . . . . . . . . . . . . . . . 42
+ 8.3.2.7. foreach . . . . . . . . . . . . . . . . . . . . . . . . . 43
+ 8.4. break, return, continue . . . . . . . . . . . . . . . . . . . 45
+ 9. Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
+ 9.1. Declaring Functions . . . . . . . . . . . . . . . . . . . . . 46
+ 9.2. Parameter Passing Mechanism . . . . . . . . . . . . . . . . . 46
+ 9.3. Referencing Variables . . . . . . . . . . . . . . . . . . . . 48
+ 9.4. Functions with a Variable Number of Arguments . . . . . . . . 49
+ 9.5. Returning Values . . . . . . . . . . . . . . . . . . . . . . 51
+ 9.6. Multiple Assignment Statement . . . . . . . . . . . . . . . . 52
+ 9.7. Exit-Blocks . . . . . . . . . . . . . . . . . . . . . . . . . 54
+ 10. Name Spaces . . . . . . . . . . . . . . . . . . . . . . . . . 56
+ 11. Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
+ 11.1. Creating Arrays . . . . . . . . . . . . . . . . . . . . . . 58
+ 11.1.1. Range Arrays . . . . . . . . . . . . . . . . . . . . . . . 58
+ 11.1.2. Creating arrays via the dereference operator . . . . . . . 59
+ 11.2. Reshaping Arrays . . . . . . . . . . . . . . . . . . . . . . 60
+ 11.3. Indexing Arrays . . . . . . . . . . . . . . . . . . . . . . 60
+ 11.4. Arrays and Variables . . . . . . . . . . . . . . . . . . . . 64
+ 11.5. Using Arrays in Computations . . . . . . . . . . . . . . . . 65
+ 12. Associative Arrays . . . . . . . . . . . . . . . . . . . . . . 69
+ 13. Structures and User-Defined Types . . . . . . . . . . . . . . 71
+ 13.1. Defining a Structure . . . . . . . . . . . . . . . . . . . . 71
+ 13.2. Accessing the Fields of a Structure . . . . . . . . . . . . 72
+ 13.3. Linked Lists . . . . . . . . . . . . . . . . . . . . . . . . 72
+ 13.4. Defining New Types . . . . . . . . . . . . . . . . . . . . . 75
+ 14. Error Handling . . . . . . . . . . . . . . . . . . . . . . . . 77
+ 14.1. Error-Blocks . . . . . . . . . . . . . . . . . . . . . . . . 77
+ 14.2. Clearing Errors . . . . . . . . . . . . . . . . . . . . . . 78
+ 15. Loading Files: evalfile and autoload . . . . . . . . . . . . . 80
+ 16. File Input/Output . . . . . . . . . . . . . . . . . . . . . . 81
+ 16.1. Input/Output via stdio . . . . . . . . . . . . . . . . . . . 81
+ 16.1.1. Stdio Overview . . . . . . . . . . . . . . . . . . . . . . 81
+ 16.1.2. Stdio Examples . . . . . . . . . . . . . . . . . . . . . . 82
+ 16.2. POSIX I/O . . . . . . . . . . . . . . . . . . . . . . . . . 84
+ 16.3. Advanced I/O techniques . . . . . . . . . . . . . . . . . . 84
+ 16.3.1. Example: Reading /var/log/wtmp . . . . . . . . . . . . . . 86
+ 17. Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . 88
+ 18. Regular Expressions . . . . . . . . . . . . . . . . . . . . . 89
+ 18.1. S-Lang RE Syntax . . . . . . . . . . . . . . . . . . . . . 89
+ 18.2. Differences between S-Lang and egrep REs . . . . . . . . . 90
+ 19. Future Directions . . . . . . . . . . . . . . . . . . . . . . 91
+ A. Copyright . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
+ A.1. The GNU Public License . . . . . . . . . . . . . . . . . . . 92
+ A.2. The Artistic License . . . . . . . . . . . . . . . . . . . . 98
+
+
+
diff --git a/libslang/doc/text/slangfun.txt b/libslang/doc/text/slangfun.txt
new file mode 100644
index 0000000..3f35b89
--- /dev/null
+++ b/libslang/doc/text/slangfun.txt
@@ -0,0 +1,5943 @@
+_isnull
+
+ SYNOPSIS
+ Check array for NULL elements
+
+ USAGE
+ Char_Type[] = _isnull (a[])
+
+ DESCRIPTION
+ This function may be used to test for the presence of NULL elements
+ of an array. Specifically, it returns a `Char_Type' array of
+ with the same number of elements and dimensionality of the input
+ array. If an element of the input array is NULL, then the
+ corresponding element of the output array will be set to 1,
+ otherwise it will be set to 0.
+
+ EXAMPLE
+ Set all NULL elements of a string array `A' to the empty
+ string `""':
+
+ A[where(_isnull(A))] = "";
+
+
+ NOTES
+ It is important to understand the difference between `A==NULL'
+ and `_isnull(A)'. The latter tests all elements of `A'
+ against NULL, whereas the former only tests `A' itself.
+
+ SEE ALSO
+ where, array_map
+--------------------------------------------------------------
+
+_reshape
+
+ SYNOPSIS
+ Copy an array to a new shape
+
+ USAGE
+ Array_Type _reshape (Array_Type A, Array_Type I)
+
+ DESCRIPTION
+ The `_reshape' function creates a copy of an array `A',
+ reshapes it to the form specified by `I' and returns the result.
+ The elements of `I' specify the new dimensions of the copy of
+ `A' and must be consistent with the number of elements `A'.
+
+ EXAMPLE
+ If `A' is a `100' element 1-d array, a new array 2-d array of
+ size `20' by `5' may be created from the elements of `A'
+ by
+
+ A = _reshape (A, [20, 5]);
+
+ In this example, the original array was no longer needed. Hence, it
+ is preferable to make use of the `__tmp' operator to avoid the
+ creation of a new array, i.e.,
+
+ A = _reshape (__tmp(A), [20,5]);
+
+
+ NOTES
+ The `reshape' function performs a similar function to
+ `_reshape'. In fact, the `_reshape' function could have been
+ implemented via:
+
+ define _reshape (a, i)
+ {
+ a = @a; % Make a new copy
+ reshape (a, i);
+ return a;
+ }
+
+
+ SEE ALSO
+ reshape, array_info
+--------------------------------------------------------------
+
+array_info
+
+ SYNOPSIS
+ Returns information about an array
+
+ USAGE
+ (Array_Type, Integer_Type, DataType_Type) array_info (Array_Type a)
+
+ DESCRIPTION
+ The `array_info' function returns information about the array `a'.
+ It returns three values: an 1-d integer array specifying the
+ size of each dimension of `a', the number of dimensions of
+ `a', and the data type of `a'.
+
+ EXAMPLE
+ The `array_info' function may be used to find the number of rows
+ of an array:
+
+ define num_rows (a)
+ {
+ variable dims, num_dims, data_type;
+
+ (dims, num_dims, data_type) = array_info (a);
+ return dims [0];
+ }
+
+ For 1-d arrays, this information is more easily obtained from the
+ `length' function.
+
+ SEE ALSO
+ typeof, reshape, length, _reshape
+--------------------------------------------------------------
+
+array_map
+
+ SYNOPSIS
+ Apply a function to each element of an array
+
+ USAGE
+ Array_Type array_map (type, func, arg0, ...)
+
+ DataType_Type type;
+ Ref_Type func;
+
+
+ DESCRIPTION
+ The `array_map' function may be used to apply a function to each
+ element of an array and returns the result as an array of a
+ specified type. The `type' parameter indicates what kind of
+ array should be returned and generally corresponds to the return
+ type of the function. The `arg0' parameter should be an array
+ and is used to determine the dimensions of the resulting array. If
+ any subsequent arguments correspond to an array of the same size,
+ then those array elements will be passed in parallel with the first
+ arrays arguments.
+
+ EXAMPLE
+ The first example illustrates how to apply the `strlen' function
+ to an array of strings:
+
+ S = ["", "Train", "Subway", "Car"];
+ L = array_map (Integer_Type, &strlen, S);
+
+ This is equivalent to:
+
+ S = ["", "Train", "Subway", "Car"];
+ L = Integer_Type [length (S)];
+ for (i = 0; i < length (S); i++) L[i] = strlen (S[i]);
+
+
+ Now consider an example involving the `strcat' function:
+
+ files = ["slang", "slstring", "slarray"];
+
+ exts = ".c";
+ cfiles = array_map (String_Type, &strcat, files, exts);
+ % ==> cfiles = ["slang.c slstring.c slarray.c"];
+
+ exts = [".a",".b",".c"];
+ xfiles = array_map (String_Type, &strcat, files, exts);
+ % ==> xfiles = ["slang.a", "slstring.b", "slarray.c"];
+
+
+ NOTES
+ Many mathemetical functions already work transparantly on arrays.
+ For example, the following two statements produce identical results:
+
+ B = sin (A);
+ B = array_map (Double_Type, &sin, A);
+
+
+ SEE ALSO
+ array_info, strlen, strcat, sin
+--------------------------------------------------------------
+
+array_sort
+
+ SYNOPSIS
+ Sort an array
+
+ USAGE
+ Array_Type array_sort (Array_Type a [, String_Type or Ref_Type f])
+
+ DESCRIPTION
+ `array_sort' sorts the array `a' into ascending order and
+ returns an integer array that represents the result of the sort. If
+ the optional second parameter `f' is present, the function
+ specified by `f' will be used to compare elements of `a';
+ otherwise, a built-in sorting function will be used.
+
+ If `f' is present, then it must be either a string representing
+ the name of the comparison function, or a reference to the function.
+ The sort function represented by `f' must be a S-Lang
+ user-defined function that takes two arguments. The function must
+ return an integer that is less than zero if the first parameter is
+ considered to be less than the second, zero if they are equal, and a
+ value greater than zero if the first is greater than the second.
+
+ If the comparision function is not specified, then a built-in comparison
+ function appropriate for the data type will be used. For example,
+ if `a' is an array of character strings, then the sort will be
+ preformed using `strcmp'.
+
+ The integer array returned by this function is simply an index that
+ indicates the order of the sorted array. The input array `a' is
+ not changed.
+
+ EXAMPLE
+ An array of strings may be sorted using the `strcmp' function
+ since it fits the specification for the sorting function described
+ above:
+
+ variable A = String_Type [3];
+ A[0] = "gamma"; A[1] = "alpha"; A[2] = "beta";
+
+ variable I = array_sort (A, &strcmp);
+
+ Alternatively, one may use
+
+ variable I = array_sort (A);
+
+ to use the built-in comparison function.
+
+ After the `array_sort' has executed, the variable `I' will
+ have the values `[2, 0, 1]'. This array can be used to
+ re-shuffle the elements of `A' into the sorted order via the
+ array index expression `A = A[I]'.
+
+ SEE ALSO
+ strcmp
+--------------------------------------------------------------
+
+cumsum
+
+ SYNOPSIS
+ Compute the cumulative sum of an array
+
+ USAGE
+ result = cumsum (Array_Type a [, Int_Type dim])
+
+ DESCRIPTION
+ The `cumsum' function performs a cumulative sum over the
+ elements of a numeric array and returns the resulting. If a second
+ argument is given, then it specifies the dimension of the array to
+ be summed over. For example, the cumulative sum of
+ `[1,2,3,4]', is the array `[1,1+2,1+2+3,1+2+3+4]', i.e.,
+ `[1,3,6,10]'.
+
+ SEE ALSO
+ sum
+--------------------------------------------------------------
+
+init_char_array
+
+ SYNOPSIS
+ Initialize an array of characters
+
+ USAGE
+ init_char_array (Array_Type a, String_Type s)
+
+ DESCRIPTION
+ The `init_char_array' function may be used to initialize a
+ character array `a' by setting the elements of the array
+ `a' to the corresponding characters of the string `s'.
+
+ EXAMPLE
+ The statements
+
+ variable a = Char_Type [10];
+ init_char_array (a, "HelloWorld");
+
+ creates an character array and initializes its elements to the
+ characters in the string `"HelloWorld"'.
+
+ NOTES
+ The character array must be large enough to hold all the characters
+ of the initialization string.
+
+ SEE ALSO
+ bstring_to_array, strlen, strcat
+--------------------------------------------------------------
+
+length
+
+ SYNOPSIS
+ Get the length of an object
+
+ USAGE
+ Integer_Type length (obj)
+
+ DESCRIPTION
+ The `length' function may be used to get information about the
+ length of an object. For simple scalar data-types, it returns 1.
+ For arrays, it returns the total number of elements of the array.
+
+ NOTES
+ If `obj' is a string, `length' returns 1 because a
+ `String_Type' object is considered to be a scalar. To get the
+ number of characters in a string, use the `strlen' function.
+
+ SEE ALSO
+ array_info, typeof, strlen
+--------------------------------------------------------------
+
+max
+
+ SYNOPSIS
+ Get the maximum value of an array
+
+ USAGE
+ result = max (Array_Type a [,Int_Type dim])
+
+ DESCRIPTION
+ The `max' function examines the elements of a numeric array and
+ returns the value of the largest element. If a second argument is
+ given, then it specifies the dimension of the array to be searched.
+ In this case, an array of dimension one less than that of the input array
+ will be returned with the corresponding elements in the specified
+ dimension replaced by the minimum value in that dimension.
+
+ EXAMPLE
+ Consider the 2-d array
+
+ 1 2 3 4 5
+ 6 7 8 9 10
+
+ generated by
+
+ a = _reshape ([1:10], [2, 5]);
+
+ Then `max(a)' will return `10', and `max(a,0)' will return
+ a 1-d array with elements
+
+ 6 7 8 9 10
+
+
+ SEE ALSO
+ max, sum, reshape
+--------------------------------------------------------------
+
+min
+
+ SYNOPSIS
+ Get the minimum value of an array
+
+ USAGE
+ result = min (Array_Type a [,Int_Type dim])
+
+ DESCRIPTION
+ The `min' function examines the elements of a numeric array and
+ returns the value of the smallest element. If a second argument is
+ given, then it specifies the dimension of the array to be searched.
+ In this case, an array of dimension one less than that of the input array
+ will be returned with the corresponding elements in the specified
+ dimension replaced by the minimum value in that dimension.
+
+ EXAMPLE
+ Consider the 2-d array
+
+ 1 2 3 4 5
+ 6 7 8 9 10
+
+ generated by
+
+ a = _reshape ([1:10], [2, 5]);
+
+ Then `min(a)' will return `1', and `min(a,0)' will return
+ a 1-d array with elements
+
+ 1 2 3 4 5
+
+
+ SEE ALSO
+ max, sum, reshape
+--------------------------------------------------------------
+
+reshape
+
+ SYNOPSIS
+ Reshape an array
+
+ USAGE
+ reshape (Array_Type A, Array_Type I)
+
+ DESCRIPTION
+ The `reshape' function changes the size of `A' to have the size
+ specified by the 1-d integer array `I'. The elements of `I'
+ specify the new dimensions of `A' and must be consistent with
+ the number of elements `A'.
+
+ EXAMPLE
+ If `A' is a `100' element 1-d array, it can be changed to a
+ 2-d `20' by `5' array via
+
+ reshape (A, [20, 5]);
+
+ However, `reshape(A, [11,5])' will result in an error because
+ the `[11,5]' array specifies `55' elements.
+
+ NOTES
+ Since `reshape' modifies the shape of an array, and arrays are
+ treated as references, then all references to the array will
+ reference the new shape. If this effect is unwanted, then use the
+ `_reshape' function instead.
+
+ SEE ALSO
+ _reshape, array_info
+--------------------------------------------------------------
+
+sum
+
+ SYNOPSIS
+ Sum over the elements of an array
+
+ USAGE
+ result = sum (Array_Type a [, Int_Type dim])
+
+ DESCRIPTION
+ The `sum' function sums over the elements of a numeric array and
+ returns its result. If a second argument is given, then it
+ specifies the dimension of the array to be summed over. In this
+ case, an array of dimension one less than that of the input array
+ will be returned.
+
+ If the input array is an integer type, then the resulting value will
+ be a `Double_Type'. If the input array is a `Float_Type',
+ then the result will be a `Float_Type'.
+
+ EXAMPLE
+ The mean of an array `a' of numbers is
+
+ sum(a)/length(a)
+
+
+ SEE ALSO
+ cumsum, transpose, reshape
+--------------------------------------------------------------
+
+transpose
+
+ SYNOPSIS
+ Transpose an array
+
+ USAGE
+ Array_Type transpose (Array_Type a)
+
+ DESCRIPTION
+ The `transpose' function returns the transpose of a specified
+ array. By definition, the transpose of an array, say one with
+ elements `a[i,j,...k]' is an array whose elements are
+ `a[k,...,j,i]'.
+
+ SEE ALSO
+ _reshape, reshape, sum, array_info
+--------------------------------------------------------------
+
+where
+
+ SYNOPSIS
+ Get indices where an integer array is non-zero
+
+ USAGE
+ Array_Type where (Array_Type a)
+
+ DESCRIPTION
+ The `where' function examines an numeric array `a' and
+ returns an integer array giving the indices of `a'
+ where the corresponding element of `a' is non-zero.
+
+ Although this function may appear to be simple or even trivial, it
+ is arguably one of the most important and powerful functions for
+ manipulating arrays.
+
+ EXAMPLE
+ Consider the following:
+
+ variable X = [0.0:10.0:0.01];
+ variable A = sin (X);
+ variable I = where (A < 0.0);
+ A[I] = cos (X) [I];
+
+ Here the variable `X' has been assigned an array of doubles
+ whose elements range from `0.0' through `10.0' in
+ increments of `0.01'. The second statement assigns `A' to
+ an array whose elements are the `sin' of the elements of `X'.
+ The third statement uses the where function to get the indices of
+ the elements of `A' that are less than `0.0'. Finally, the
+ last statement substitutes into `A' the `cos' of the
+ elements of `X' at the positions of `A' where the
+ corresponding `sin' is less than `0'. The end result is
+ that the elements of `A' are a mixture of sines and cosines.
+
+ SEE ALSO
+ array_info, sin, cos
+--------------------------------------------------------------
+
+assoc_delete_key
+
+ SYNOPSIS
+ Delete a key from an Associative Array
+
+ USAGE
+ assoc_delete_key (Assoc_Type a, String_Type k)
+
+ DESCRIPTION
+ The `assoc_delete_key' function deletes a key given by `k'
+ from the associative array `a'. If the specified key does not
+ exist in `a', then this function has no effect.
+
+ SEE ALSO
+ assoc_key_exists, assoc_get_keys
+--------------------------------------------------------------
+
+assoc_get_keys
+
+ SYNOPSIS
+ Return all the key names of an Associative Array
+
+ USAGE
+ String_Type[] assoc_get_keys (Assoc_Type a)
+
+ DESCRIPTION
+ This function returns all the key names of an associative array
+ `a' as an ordinary one dimensional array of strings. If the
+ associative array contains no keys, an empty array will be returned.
+
+ EXAMPLE
+ The following function computes the number of keys in an associative
+ array:
+
+ define get_num_elements (a)
+ {
+ return length (assoc_get_keys (a));
+ }
+
+
+ SEE ALSO
+ assoc_get_values, assoc_key_exists, assoc_delete_key, length
+--------------------------------------------------------------
+
+assoc_get_values
+
+ SYNOPSIS
+ Return all the values of an Associative Array
+
+ USAGE
+ Array_Type assoc_get_keys (Assoc_Type a)
+
+ DESCRIPTION
+ This function returns all the values in the associative array
+ `a' as an array of proper type. If the associative array
+ contains no keys, an empty array will be returned.
+
+ EXAMPLE
+ Suppose that `a' is an associative array of type
+ `Integer_Type', i.e., it was created via
+
+ variable a = Assoc_Type[Integer_Type];
+
+ The the following may be used to print the values of the array in
+ ascending order:
+
+ static define int_sort_fun (x, y)
+ {
+ return sign (x - y);
+ }
+ define sort_and_print_values (a)
+ {
+ variable i, v;
+
+ v = assoc_get_values (a);
+ i = array_sort (v, &int_sort_fun);
+ v = v[i];
+ foreach (v)
+ {
+ variable vi = ();
+ () = fprintf (stdout, "%d\n", vi);
+ }
+ }
+
+
+ SEE ALSO
+ assoc_get_values, assoc_key_exists, assoc_delete_key, array_sort
+--------------------------------------------------------------
+
+assoc_key_exists
+
+ SYNOPSIS
+ Check to see whether a key exists in an Associative Array
+
+ USAGE
+ Integer_Type assoc_key_exists (Assoc_Type a, String_Type k)
+
+ DESCRIPTION
+ The `assoc_key_exists' function may be used to determine whether
+ or not a specified key `k' exists in an associative array `a'.
+ It returns 1 if the key exists, or 0 if it does not.
+
+ SEE ALSO
+ assoc_get_keys, assoc_get_values, assoc_delete_key
+--------------------------------------------------------------
+
+array_to_bstring
+
+ SYNOPSIS
+ Convert an array to a binary string
+
+ USAGE
+ BString_Type array_to_bstring (Array_Type a)
+
+ DESCRIPTION
+ The `array_to_bstring' function returns the elements of an
+ array `a' as a binary string.
+
+ SEE ALSO
+ bstring_to_array, init_char_array
+--------------------------------------------------------------
+
+bstring_to_array
+
+ SYNOPSIS
+ Convert a binary string to an array of characters
+
+ USAGE
+ UChar_Type[] bstring_to_array (BString_Type b)
+
+ DESCRIPTION
+ The `bstring_to_array' function returns an array of unsigned
+ characters whose elements correspond to the characters in the
+ binary string.
+
+ SEE ALSO
+ array_to_bstring, init_char_array
+--------------------------------------------------------------
+
+bstrlen
+
+ SYNOPSIS
+ Get the length of a binary string
+
+ USAGE
+ UInt_Type bstrlen (BString_Type s)
+
+ DESCRIPTION
+ The `bstrlen' function may be used to obtain the length of a
+ binary string. A binary string differs from an ordinary string (a C
+ string) in that a binary string may include null chracters.
+
+ EXAMPLE
+
+ variable s = "hello\0";
+ len = bstrlen (s); % ==> len = 6
+ len = strlen (s); % ==> len = 5
+
+
+ SEE ALSO
+ strlen, length
+--------------------------------------------------------------
+
+pack
+
+ SYNOPSIS
+ Pack objects into a binary string
+
+ USAGE
+ BString_Type pack (String_Type fmt, ...)
+
+ DESCRIPTION
+ The `pack' function combines zero or more the objects (represented
+ by the ellipses above) into a binary string acording to the format
+ string `fmt'.
+
+ The format string consists of one or more data-type specification
+ characters, and each may be followed by an optional decimal length
+ specifier. Specifically, the data-types are specified according to
+ the following table:
+
+ c char
+ C unsigned char
+ h short
+ H unsigned short
+ i int
+ I unsigned int
+ l long
+ L unsigned long
+ j 16 bit int
+ J 16 unsigned int
+ k 32 bit int
+ K 32 bit unsigned int
+ f float
+ d double
+ F 32 bit float
+ D 64 bit float
+ s character string, null padded
+ S character string, space padded
+ x a null pad character
+
+ A decimal length specifier may follow the data-type specifier. With
+ the exception of the `s' and `S' specifiers, the length
+ specifier indicates how many objects of that data type are to be
+ packed or unpacked from the string. When used with the `s' or
+ `S' specifiers, it indicates the field width to be used. If the
+ length specifier is not present, the length defaults to one.
+
+ With the exception of `c', `C', `s', `S', and
+ `x', each of these may be prefixed by a character that indicates
+ the byte-order of the object:
+
+ > big-endian order (network order)
+ < little-endian order
+ = native byte-order
+
+ The default is to use native byte order.
+
+ When unpacking via the `unpack' function, if the length
+ specifier is greater than one, then an array of that length will be
+ returned. In addition, trailing whitespace and null character are
+ stripped when unpacking an object given by the `S' specifier.
+
+ EXAMPLE
+
+ a = pack ("cc", 'A', 'B'); % ==> a = "AB";
+ a = pack ("c2", 'A', 'B'); % ==> a = "AB";
+ a = pack ("xxcxxc", 'A', 'B'); % ==> a = "\0\0A\0\0B";
+ a = pack ("h2", 'A', 'B'); % ==> a = "\0A\0B" or "\0B\0A"
+ a = pack (">h2", 'A', 'B'); % ==> a = "\0\xA\0\xB"
+ a = pack ("<h2", 'A', 'B'); % ==> a = "\0B\0A"
+ a = pack ("s4", "AB", "CD"); % ==> a = "AB\0\0"
+ a = pack ("s4s2", "AB", "CD"); % ==> a = "AB\0\0CD"
+ a = pack ("S4", "AB", "CD"); % ==> a = "AB "
+ a = pack ("S4S2", "AB", "CD"); % ==> a = "AB CD"
+
+
+ SEE ALSO
+ unpack, sizeof_pack, pad_pack_format, sprintf
+--------------------------------------------------------------
+
+pad_pack_format
+
+ SYNOPSIS
+ Add padding to a pack format
+
+ USAGE
+ BString_Type pad_pack_format (String_Type fmt)
+
+ DESCRIPTION
+ The `pad_pack_format' function may be used to add the
+ appropriate padding to the format `fmt' such that the data types
+ specified by the format will be properly aligned for the system.
+ This is especially important when reading or writing files that
+ assume the native alignment.
+
+ See the S-Lang User's Guide for more information about the use of
+ this function.
+
+ SEE ALSO
+ pack, unpack, sizeof_pack
+--------------------------------------------------------------
+
+sizeof_pack
+
+ SYNOPSIS
+ Compute the size implied by a pack format string
+
+ USAGE
+ UInt_Type sizeof_pack (String_Type fmt)
+
+ DESCRIPTION
+ The `sizeof_pack' function returns the size of the binary string
+ represented by the format string `fmt'. This information may be
+ needed when reading a structure from a file.
+
+ NOTES
+
+ SEE ALSO
+ pack, unpack, pad_pack_format
+--------------------------------------------------------------
+
+unpack
+
+ SYNOPSIS
+ Unpack Objects from a Binary String
+
+ USAGE
+ (...) = unpack (String_Type fmt, BString_Type s)
+
+ DESCRIPTION
+ The `unpack' function unpacks objects from a binary string
+ `s' according to the format `fmt' and returns the objects to
+ the stack in the order in which they were unpacked. See the
+ documentation of the `pack' function for details about the
+ format string.
+
+ EXAMPLE
+
+ (x,y) = unpack ("cc", "AB"); % ==> x = 'A', y = 'B'
+ x = unpack ("c2", "AB"); % ==> x = ['A', 'B']
+ x = unpack ("x<H", "\0\xAB\xCD"); % ==> x = 0xCDABuh
+ x = unpack ("xxs4", "a b c\0d e f"); % ==> x = "b c\0"
+ x = unpack ("xxS4", "a b c\0d e f"); % ==> x = "b c"
+
+
+ SEE ALSO
+ pack, sizeof_pack, pad_pack_format
+--------------------------------------------------------------
+
+_clear_error
+
+ SYNOPSIS
+ Clear an error condition
+
+ USAGE
+ _clear_error ()
+
+ DESCRIPTION
+ This function may be used in error-blocks to clear the error that
+ triggered execution of the error block. Execution resumes following
+ the statement, in the scope of the error-block, that triggered the
+ error.
+
+ EXAMPLE
+ Consider the following wrapper around the `putenv' function:
+
+ define try_putenv (name, value)
+ {
+ variable status;
+ ERROR_BLOCK
+ {
+ _clear_error ();
+ status = -1;
+ }
+ status = 0;
+ putenv (sprintf ("%s=%s", name, value);
+ return status;
+ }
+
+ If `putenv' fails, it generates an error condition, which the
+ `try_putenv' function catches and clears. Thus `try_putenv'
+ is a function that returns `-1' upon failure and `0' upon
+ success.
+
+ SEE ALSO
+ _trace_function, _slangtrace, _traceback
+--------------------------------------------------------------
+
+_debug_info
+
+ SYNOPSIS
+ Configure debugging information
+
+ USAGE
+ Integer_Type _debug_info
+
+ DESCRIPTION
+ The `_debug_info' variable controls whether or not extra code
+ should be generated for additional debugging and traceback
+ information. Currently, if `_debug_info' is zero, no extra code
+ will be generated; otherwise extra code will be inserted into the
+ compiled bytecode for additional debugging data.
+
+ The value of this variable is local to each compilation unit and
+ setting its value in one unit has no effect upon its value in other
+ units.
+
+ EXAMPLE
+
+ _debug_info = 1; % Enable debugging information
+
+
+ NOTES
+ Setting this variable to a non-zero value may slow down the
+ interpreter somewhat.
+
+ SEE ALSO
+ _traceback, _slangtrace
+--------------------------------------------------------------
+
+_slangtrace
+
+ SYNOPSIS
+ Turn function tracing on or off.
+
+ USAGE
+ Integer_Type _slangtrace
+
+ DESCRIPTION
+ The `_slangtrace' variable is a debugging aid that when set to a
+ non-zero value enables tracing when function declared by
+ `_trace_function' is entered. If the value is greater than
+ zero, both intrinsic and user defined functions will get traced.
+ However, if set to a value less than zero, intrinsic functions will
+ not get traced.
+
+ SEE ALSO
+ _trace_function, _traceback, _print_stack
+--------------------------------------------------------------
+
+_trace_function
+
+ SYNOPSIS
+ Set the function to trace
+
+ USAGE
+ _trace_function (String_Type f)
+
+ DESCRIPTION
+ `_trace_function' declares that the S-Lang function with name
+ `f' is to be traced when it is called. Calling
+ `_trace_function' does not in itself turn tracing on. Tracing
+ is turned on only when the variable `_slangtrace' is non-zero.
+
+ SEE ALSO
+ _slangtrace, _traceback
+--------------------------------------------------------------
+
+_traceback
+
+ SYNOPSIS
+ Generate a traceback upon error
+
+ USAGE
+ Integer_Type _traceback
+
+ DESCRIPTION
+ `_traceback' is an intrinsic integer variable whose value
+ controls whether or not a traceback of the call stack is to be
+ generated upon error. If `_traceback' is greater than zero, a
+ full traceback will be generated, which includes the values of local
+ variables. If the value is less than zero, a traceback will be
+ generated without local variable information, and if
+ `_traceback' is zero the traceback will not be generated.
+
+ Local variables are represented in the form `$n' where `n' is an
+ integer numbered from zero. More explicitly, `$0' represents the
+ first local variable, `$1' represents the second, and so on.
+ Please note that function parameters are local variables and that the
+ first parameter corresponds to `$0'.
+
+ SEE ALSO
+ _slangtrace, error
+--------------------------------------------------------------
+
+chdir
+
+ SYNOPSIS
+ Change the current working directory.
+
+ USAGE
+ Integer_Type chdir (String_Type dir)
+
+ DESCRIPTION
+ The `chdir' function may be used to changed the current working
+ directory to the directory specified by `dir'. Upon success it
+ returns zero; however, upon failure it returns `-1' and sets
+ `errno' accordingly.
+
+ SEE ALSO
+ mkdir, stat_file
+--------------------------------------------------------------
+
+chmod
+
+ SYNOPSIS
+ Change the mode of a file
+
+ USAGE
+ Integer_Type chmod (String_Type file, Integer_Type mode)
+
+ DESCRIPTION
+ The `chmod' function changes the permissions of `file' to those
+ specified by `mode'. It returns `0' upon success, or
+ `-1' upon failure setting `errno' accordingly.
+
+ See the system specific documentation for the C library
+ function `chmod' for a discussion of the `mode' parameter.
+
+ SEE ALSO
+ chown, stat_file
+--------------------------------------------------------------
+
+chown
+
+ SYNOPSIS
+ Change the owner of a file
+
+ USAGE
+ Integer_Type chown (String_Type file, Integer_Type uid, Integer_Type gid)
+
+ DESCRIPTION
+ The `chown' function is used to change the user-id and group-id of
+ `file' to `uid' and `gid', respectively. It returns
+ `zero' upon success and `-1' upon failure, with `errno'
+ set accordingly.
+
+ NOTES
+ On most systems, only the super user can change the ownership of a
+ file.
+
+ Some systems do not support this function.
+
+ SEE ALSO
+ chmod, stat_file
+--------------------------------------------------------------
+
+getcwd
+
+ SYNOPSIS
+ Get the current working directory
+
+ USAGE
+ String_Type getcwd ()
+
+ DESCRIPTION
+ The `getcwd' function returns the absolute pathname of the
+ current working directory. If an error occurs or it cannot
+ determine the working directory, it returns `NULL' and sets
+ `errno' accordingly.
+
+ NOTES
+ Under Unix, OS/2, and MSDOS, the pathname returned by this function
+ includes the trailing slash character. Some versions also include
+ the drive specifier.
+
+ SEE ALSO
+ mkdir, chdir, errno
+--------------------------------------------------------------
+
+listdir
+
+ SYNOPSIS
+ Get a list of the files in a directory
+
+ USAGE
+ String_Type[] listdir (String_Type dir)
+
+ DESCRIPTION
+ The `listdir' function returns the directory listing of all the
+ files in the specified directory `dir' as an array of strings.
+ It does not return the special files `".."' and `"."' as
+ part of the list.
+
+ SEE ALSO
+ stat_file, stat_is, length
+--------------------------------------------------------------
+
+lstat_file
+
+ SYNOPSIS
+ Get information about a symbolic link
+
+ USAGE
+ Struct_Type lstat_file (String_Type file)
+
+ DESCRIPTION
+ The `lstat_file' function behaves identically to `stat_file'
+ but if `file' is a symbolic link, `lstat_file' returns
+ information about the link itself, and not the file that it
+ references.
+
+ See the documentation for `stat_file' for more information.
+
+ NOTES
+ On systems that do not support symbolic links, there is no
+ difference between this function and the `stat_file' function.
+
+ SEE ALSO
+ stat_file, readlink
+--------------------------------------------------------------
+
+mkdir
+
+ SYNOPSIS
+ Create a new directory
+
+ USAGE
+ Integer_Type mkdir (String_Type dir, Integer_Type mode)
+
+ DESCRIPTION
+ The `mkdir' function creates a directory whose name is specified
+ by the `dir' parameter with permissions specified by `mode'.
+ Upon success `mkdir' returns zero, or it returns `-1' and
+ sets `errno' accordingly. In particular, if the directory
+ already exists, the function will fail and set errno to
+ `EEXIST'.
+
+ EXAMPLE
+
+ define my_mkdir (dir)
+ {
+ if (0 == mkdir (dir, 0777)) return;
+ if (errno == EEXIST) return;
+ verror ("mkdir %s failed: %s", dir, errno_string (errno));
+ }
+
+
+ NOTES
+ The `mode' parameter may not be meaningful on all systems. On
+ systems where it is meaningful, the actual permissions on the newly
+ created directory are modified by the process's umask.
+
+ SEE ALSO
+ rmdir, getcwd, chdir, fopen, errno
+--------------------------------------------------------------
+
+readlink
+
+ SYNOPSIS
+ String_Type readlink (String_Type path)
+
+ USAGE
+ Get the value of a symbolic link
+
+ DESCRIPTION
+ The `readlink' function returns the value of a symbolic link and
+ returns it as a string. Upon failure, NULL is returned and
+ `errno' set accordingly.
+
+ NOTES
+ Not all systems support this function.
+
+ SEE ALSO
+ lstat_file, stat_file, stat_is
+--------------------------------------------------------------
+
+remove
+
+ SYNOPSIS
+ Delete a file
+
+ USAGE
+ Integer_Type remove (String_Type file)
+
+ DESCRIPTION
+ The `remove' function deletes a file. It returns 0 upon
+ success, or -1 upon error and sets `errno' accordingly.
+
+ SEE ALSO
+ rename, rmdir
+--------------------------------------------------------------
+
+rename
+
+ SYNOPSIS
+ Rename a file
+
+ USAGE
+ Integer_Type rename (String_Type old, String_Type new)
+
+ DESCRIPTION
+ The `rename' function renames a file from `old' to `new'
+ moving it between directories if necessary. This function may fail
+ if the directories do not refer to the same file system. It returns
+ 0 upon success, or -1 upon error and sets `errno' accordingly.
+
+ SEE ALSO
+ remove, errno
+--------------------------------------------------------------
+
+rmdir
+
+ SYNOPSIS
+ Remove a directory
+
+ USAGE
+ Integer_Type rmdir (String_Type dir)
+
+ DESCRIPTION
+ The `rmdir' function deletes a specified directory. It returns
+ 0 upon success or -1 upon error and sets `errno' accordingly.
+
+ NOTES
+ The directory must be empty before it can be removed.
+
+ SEE ALSO
+ rename, remove, mkdir
+--------------------------------------------------------------
+
+stat_file
+
+ SYNOPSIS
+ Get information about a file
+
+ USAGE
+ Struct_Type stat_file (String_Type file)
+
+ DESCRIPTION
+ The `stat_file' function returns information about `file'
+ through the use of the system `stat' call. If the stat call
+ fails, the function returns `NULL' and sets errno accordingly.
+ If it is successful, it returns a stat structure with the following
+ integer fields:
+
+ st_dev
+ st_ino
+ st_mode
+ st_nlink
+ st_uid
+ st_gid
+ st_rdev
+ st_size
+ st_atime
+ st_mtime
+ st_ctime
+
+ See the man page for `stat' for a discussion of these fields.
+
+ EXAMPLE
+ The following example shows how the `stat_file' function may be
+ used to get the size of a file:
+
+ define file_size (file)
+ {
+ variable st;
+ st = stat_file(file);
+ if (st == NULL) verror ("Unable to stat %s", file);
+ return st.st_size;
+ }
+
+
+ SEE ALSO
+ lstat_file, stat_is
+--------------------------------------------------------------
+
+stat_is
+
+ SYNOPSIS
+ Parse the var{st_mode
+
+ USAGE
+ Char_Type stat_is (String_Type type, Integer_Type st_mode)
+
+ DESCRIPTION
+ The `stat_is' function returns a signed character value about
+ the type of file specified by `st_mode'. Specifically,
+ `type' must be one of the strings:
+
+ "sock" (socket)
+ "fifo" (fifo)
+ "blk" (block device)
+ "chr" (character device)
+ "reg" (regular file)
+ "lnk" (link)
+ "dir" (dir)
+
+ It returns a non-zero value if `st_mode' corresponds to
+ `type'.
+
+ EXAMPLE
+ The following example illustrates how to use the `stat_is'
+ function to determine whether or not a file is a directory:
+
+ define is_directory (file)
+ {
+ variable st;
+
+ st = stat_file (file);
+ if (st == NULL) return 0;
+ return stat_is ("dir", st.st_mode);
+ }
+
+
+ SEE ALSO
+ stat_file, lstat_file
+--------------------------------------------------------------
+
+autoload
+
+ SYNOPSIS
+ Load a function from a file
+
+ USAGE
+ autoload (String_Type funct, String_Type file)
+
+ DESCRIPTION
+ The `autoload' function is used to declare `funct' to the
+ interpreter and indicate that it should be loaded from `file' when
+ it is actually used.
+
+ EXAMPLE
+ Suppose `bessel_j0' is a function defined in the file
+ `bessel.sl'. Then the statement
+
+ autoload ("bessel_j0", "bessel.sl");
+
+ will cause `bessel.sl' to be loaded prior to the execution of
+ `bessel_j0'
+
+ SEE ALSO
+ evalfile
+--------------------------------------------------------------
+
+byte_compile_file
+
+ SYNOPSIS
+ Compile a file to byte-code for faster loading.
+
+ USAGE
+ byte_compile_file (String_Type file, Integer_Type method)
+
+ DESCRIPTION
+ The `byte_compile_file' function byte-compiles `file'
+ producing a new file with the same name except a `'c'' is added
+ to the output file name. For example, `file' is
+ `"site.sl"', then the function produces a new file named
+ `site.slc'.
+
+ NOTES
+ The `method' parameter is not used in the current
+ implementation. Its use is reserved for the future. For now, set
+ it to `0'.
+
+ SEE ALSO
+ evalfile
+--------------------------------------------------------------
+
+eval
+
+ SYNOPSIS
+ Interpret a string as slang code
+
+ USAGE
+ eval (String_Type expression, [,String_Type namespace])
+
+ DESCRIPTION
+ The `eval' function parses a string as S-Lang code and executes the
+ result. If called with the optional namespace argument, then the
+ string will be evaluated in the specified namespace.
+
+ This is a useful function in many contexts such as dynamically
+ generating function definitions where there is no way to generate
+ them otherwise.
+
+ EXAMPLE
+
+ if (0 == is_defined ("my_function"))
+ eval ("define my_function () { message (\"my_function\"); }");
+
+
+ SEE ALSO
+ is_defined, autoload, evalfile
+--------------------------------------------------------------
+
+evalfile
+
+ SYNOPSIS
+ Interpret a file containing slang code.
+
+ USAGE
+ Integer_Type evalfile (String_Type file, [,String_Type namespace])
+
+ DESCRIPTION
+ The `evalfile' function loads `file' into the interpreter
+ and executes it. If called with the optional namespace argument,
+ the file will be loaded into the specified namespace, which will be
+ created if necessary. If no errors were encountered, `1' will
+ be returned; otherwise, a S-Lang error will be generated and the
+ function will return zero.
+
+ EXAMPLE
+
+ define load_file (file)
+ {
+ ERROR_BLOCK { _clear_error (); }
+ () = evalfile (file);
+ }
+
+
+ NOTES
+ For historical reasons, the return value of this function is not
+ really useful.
+
+ The file is searched along an application-defined load-path. The
+ `get_slang_load_path' and `set_slang_load_path' functions
+ may be used to set and query the path.
+
+ SEE ALSO
+ eval, autoload, set_slang_load_path, get_slang_load_path
+--------------------------------------------------------------
+
+get_slang_load_path
+
+ SYNOPSIS
+ Get the value of the interpreter's load-path
+
+ USAGE
+ String_Type get_slang_load_path ()
+
+ DESCRIPTION
+ This function retrieves the value of the delimiter-separated search
+ path used for loading files.
+
+ NOTES
+ Some applications may not support the built-in load-path searching
+ facility provided by the underlying library.
+
+ SEE ALSO
+
+--------------------------------------------------------------
+
+set_slang_load_path
+
+ SYNOPSIS
+ Set the value of the interpreter's load-path
+
+ USAGE
+ set_slang_load_path (String_Type path)
+
+ DESCRIPTION
+ This function may be used to set the value of the
+ delimiter-separated search path used by the `evalfile' and
+ `autoload' functions for locating files.
+
+ EXAMPLE
+
+ public define prepend_to_slang_load_path (p)
+ {
+ variable s = stat_file (p);
+ if (s == NULL) return;
+ if (0 == stat_is ("dir", s.st_mode))
+ return;
+
+ variable d = path_get_delimiter ();
+ set_slang_load_path (strcat (p, d, get_slang_load_path ()));
+ }
+
+
+ NOTES
+ Some applications may not support the built-in load-path searching
+ facility provided by the underlying library.
+
+ SEE ALSO
+ get_slang_load_path, path_get_delimiter, evalfile, autoload
+--------------------------------------------------------------
+
+get_import_module_path
+
+ SYNOPSIS
+ Get the search path for dynamically loadable objects
+
+ USAGE
+ String_Type get_import_module_path ()
+
+ DESCRIPTION
+ The `get_import_module_path' may be used to get the search path
+ for dynamically shared objects. Such objects may be made accessable
+ to the application via the `import' function.
+
+ SEE ALSO
+ import, set_import_module_path
+--------------------------------------------------------------
+
+import
+
+ SYNOPSIS
+ Dynamically link to a specified module
+
+ USAGE
+ import (String_Type module [, String_Type namespace])
+
+ DESCRIPTION
+ The `import' function causes the run-time linker to dynamically
+ link to the shared object specified by the `module' parameter.
+ It seaches for the shared object as follows: First a search is
+ performed along all module paths specified by the application. Then
+ a search is made along the paths defined via the
+ `set_import_module_path' function. If not found, a search is
+ performed along the paths given by the `SLANG_MODULE_PATH'
+ environment variable. Finally, a system dependent search is
+ performed (e.g., using the `LD_LIBRARY_PATH' environment
+ variable).
+
+ The optional second parameter may be used to specify a namespace
+ for the intrinsic functions and variables of the module. If this
+ parameter is not present, the intrinsic objects will be placed into
+ the global namespace.
+
+ This function signals an error if the specified module is not found.
+
+ NOTES
+ The `import' function is not available on all systems.
+
+ SEE ALSO
+ set_import_module_path, use_namespace, current_namespace, getenv, evalfile
+--------------------------------------------------------------
+
+set_import_module_path
+
+ SYNOPSIS
+ Set the search path for dynamically loadable objects
+
+ USAGE
+ set_import_module_path (String_Type path_list)
+
+ DESCRIPTION
+ The `set_import_module_path' may be used to set the search path
+ for dynamically shared objects. Such objects may be made accessable
+ to the application via the `import' function.
+
+ The actual syntax for the specification of the set of paths will
+ vary according to the operating system. Under Unix, a colon
+ character is used to separate paths in `path_list'. For win32
+ systems a semi-colon is used.
+
+ SEE ALSO
+ import, get_import_module_path
+--------------------------------------------------------------
+
+_NARGS
+
+ SYNOPSIS
+ The number of parameters passed to a function
+
+ USAGE
+ Integer_Type _NARGS
+
+ EXAMPLE
+ This example uses the `_NARGS' variable to print the list of
+ values passed to the function:
+
+ define print_values ()
+ {
+ variable arg;
+
+ if (_NARGS == 0)
+ {
+ message ("Nothing to print");
+ return;
+ }
+ foreach (__pop_args (_NARGS))
+ {
+ arg = ();
+ vmessage ("Argument value is: %S", arg.value);
+ }
+ }
+
+
+ SEE ALSO
+ __pop_args, __push_args, typeof
+--------------------------------------------------------------
+
+__get_defined_symbols
+
+ SYNOPSIS
+ Get the symbols defined by the preprocessor
+
+ USAGE
+ Integer_Type __get_defined_symbols ()
+
+ DESCRIPTION
+ The `__get_defined_symbols' functions is used to get the list of
+ all the symbols defined by the S-Lang preprocessor. It pushes each
+ of the symbols on the stack followed by the number of items pushed.
+
+ SEE ALSO
+ is_defined, _apropos, _get_namespaces
+--------------------------------------------------------------
+
+__is_initialized
+
+ SYNOPSIS
+ Determine whether or not a variable has a value
+
+ USAGE
+ Integer_Type __is_initialized (Ref_Type r)
+
+ DESCRIPTION
+ This function returns non-zero of the object referenced by `r'
+ is initialized, i.e., whether it has a value. It returns 0 if the
+ referenced object has not been initialized.
+
+ EXAMPLE
+ For example, the function:
+
+ define zero ()
+ {
+ variable f;
+ return __is_initialized (&f);
+ }
+
+ will always return zero, but
+
+ define one ()
+ {
+ variable f = 0;
+ return __is_initialized (&f);
+ }
+
+ will return one.
+
+ NOTES
+ It is easy to see why a reference to the variable must be passed to
+ `__is_initialized' and not the variable itself; otherwise, the
+ value of the variable would be passed and the variable may have no
+ value if it was not initialized.
+
+ SEE ALSO
+ __get_reference, __uninitialize, is_defined, typeof, eval
+--------------------------------------------------------------
+
+_apropos
+
+ SYNOPSIS
+ Generate a list of functions and variables
+
+ USAGE
+ Array_Type _apropos (String_Type ns, String_Type s, Integer_Type flags)
+
+ DESCRIPTION
+ The `_apropos' function may be used to get a list of all defined
+ objects in the namespace `ns' whose name matches the regular
+ expression `s' and whose type matches those specified by
+ `flags'. It returns an array of strings representing the
+ matches.
+
+ The second parameter `flags' is a bit mapped value whose bits
+ are defined according to the following table
+
+ 1 Intrinsic Function
+ 2 User-defined Function
+ 4 Intrinsic Variable
+ 8 User-defined Variable
+
+
+ EXAMPLE
+
+ define apropos (s)
+ {
+ variable n, name, a;
+ a = _apropos ("Global", s, 0xF);
+
+ vmessage ("Found %d matches:", length (a));
+ foreach (a)
+ {
+ name = ();
+ message (name);
+ }
+ }
+
+ prints a list of all matches.
+
+ NOTES
+ If the namespace specifier `ns' is the empty string `""',
+ then the namespace will default to the static namespace of the
+ current compilation unit.
+
+ SEE ALSO
+ is_defined, sprintf, _get_namespaces
+--------------------------------------------------------------
+
+_function_name
+
+ SYNOPSIS
+ Returns the name of the currently executing function
+
+ USAGE
+ String_Type _function_name ()
+
+ DESCRIPTION
+ This function returns the name of the currently executing function.
+ If called from top-level, it returns the empty string.
+
+ SEE ALSO
+ _trace_function, is_defined
+--------------------------------------------------------------
+
+_get_namespaces
+
+ SYNOPSIS
+ Returns a list of namespace names
+
+ USAGE
+ String_Type[] _get_namespaces ()
+
+ DESCRIPTION
+ This function returns a string array containing the names of the
+ currently defined namespaces.
+
+ SEE ALSO
+ _apropos, use_namespace, implements, __get_defined_symbols
+--------------------------------------------------------------
+
+_slang_doc_dir
+
+ SYNOPSIS
+ Installed documentation directory
+
+ USAGE
+ String_Type _slang_doc_dir;
+
+ DESCRIPTION
+ The `_slang_doc_dir' variable is a read-only whose value
+ specifies the installation location of the S-Lang documentation.
+
+ SEE ALSO
+ get_doc_string_from_file
+--------------------------------------------------------------
+
+_slang_version
+
+ SYNOPSIS
+ The S-Lang library version number
+
+ USAGE
+ Integer_Type _slang_version
+
+ DESCRIPTION
+ The `_slang_version' variable is read-only and whose
+ value represents the number of the S-Lang library.
+
+ SEE ALSO
+ _slang_version_string
+--------------------------------------------------------------
+
+_slang_version_string
+
+ SYNOPSIS
+ The S-Lang library version number as a string
+
+ USAGE
+ String_Type _slang_version_string
+
+ DESCRIPTION
+ The `_slang_version_string' variable is read-only and whose
+ value represents the version number of the S-Lang library.
+
+ SEE ALSO
+ _slang_version
+--------------------------------------------------------------
+
+get_doc_string_from_file
+
+ SYNOPSIS
+ Read documentation from a file
+
+ USAGE
+ String_Type get_doc_string_from_file (String_Type f, String_Type t)
+
+ DESCRIPTION
+ `get_doc_string_from_file' opens the documentation file `f'
+ and searches it for topic `t'. It returns the documentation for
+ `t' upon success, otherwise it returns `NULL' upon error.
+ It will fail if `f' could not be opened or does not contain
+ documentation for the topic.
+
+ SEE ALSO
+ stat_file
+
+ SEE ALSO
+ _slang_doc_dir
+--------------------------------------------------------------
+
+is_defined
+
+ SYNOPSIS
+ Indicate whether a variable or function defined.
+
+ USAGE
+ Integer_Type is_defined (String_Type obj)
+
+ DESCRIPTION
+ This function is used to determine whether or not a function or
+ variable whose name is `obj' has been defined. If `obj' is not
+ defined, the function returns 0. Otherwise, it returns a non-zero
+ value that defpends on the type of object `obj' represents.
+ Specifically, it returns one of the following values:
+
+ +1 if an intrinsic function
+ +2 if user defined function
+ -1 if intrinsic variable
+ -2 if user defined variable
+ 0 if undefined
+
+
+ EXAMPLE
+ For example, consider the function:
+
+ define runhooks (hook)
+ {
+ if (2 == is_defined(hook)) eval(hook);
+ }
+
+ This function could be called from another S-Lang function to
+ allow customization of that function, e.g., if the function
+ represents a mode, the hook could be called to setup keybindings
+ for the mode.
+
+ SEE ALSO
+ typeof, eval, autoload, __get_reference, __is_initialized
+--------------------------------------------------------------
+
+Conj
+
+ SYNOPSIS
+ Compute the complex conjugate of a number
+
+ USAGE
+ z1 = Conj (z)
+
+ DESCRIPTION
+ The `Conj' function returns the complex conjugate of a number.
+ If its argument is an array, the `Conj' function will be applied to each
+ element and the result returned as an array.
+
+ SEE ALSO
+ Real, Imag, abs
+--------------------------------------------------------------
+
+Imag
+
+ SYNOPSIS
+ Compute the imaginary part of a number
+
+ USAGE
+ i = Imag (z)
+
+ DESCRIPTION
+ The `Imag' function returns the imaginary part of a number.
+ If its argument is an array, the `Imag' function will be applied to each
+ element and the result returned as an array.
+
+ SEE ALSO
+ Real, Conj, abs
+--------------------------------------------------------------
+
+Real
+
+ SYNOPSIS
+ Compute the real part of a number
+
+ USAGE
+ r = Real (z)
+
+ DESCRIPTION
+ The `Real' function returns the real part of a number. If its
+ argument is an array, the `Real' function will be applied to
+ each element and the result returned as an array.
+
+ SEE ALSO
+ Imag, Conj, abs
+--------------------------------------------------------------
+
+abs
+
+ SYNOPSIS
+ Compute the absolute value of a number
+
+ USAGE
+ y = abs(x)
+
+ DESCRIPTION
+ The `abs' function returns the absolute value of an arithmetic
+ type. If its argument is a complex number (`Complex_Type'),
+ then it returns the modulus. If the argument is an array, a new
+ array will be created whose elements are obtained from the original
+ array by using the `abs' function.
+
+ SEE ALSO
+ sign, sqr
+--------------------------------------------------------------
+
+acos
+
+ SYNOPSIS
+ Compute the arc-cosine of an number
+
+ USAGE
+ y = acos (x)
+
+ DESCRIPTION
+ The `acos' function computes the arc-cosine of a number and
+ returns the result as an array. If its argument is an array, the
+ `acos' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+acosh
+
+ SYNOPSIS
+ Compute the inverse cosh of an number
+
+ USAGE
+ y = acosh (x)
+
+ DESCRIPTION
+ The `acosh' function computes the inverse cosh of a number and
+ returns the result as an array. If its argument is an array, the
+ `acosh' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+asin
+
+ SYNOPSIS
+ Compute the arc-sine of an number
+
+ USAGE
+ y = asin (x)
+
+ DESCRIPTION
+ The `asin' function computes the arc-sine of a number and
+ returns the result as an array. If its argument is an array, the
+ `asin' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+asinh
+
+ SYNOPSIS
+ Compute the inverse-sinh of an number
+
+ USAGE
+ y = asinh (x)
+
+ DESCRIPTION
+ The `asinh' function computes the inverse-sinh of a number and
+ returns the result as an array. If its argument is an array, the
+ `asinh' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+atan
+
+ SYNOPSIS
+ Compute the arc-tangent of an number
+
+ USAGE
+ y = atan (x)
+
+ DESCRIPTION
+ The `atan' function computes the arc-tangent of a number and
+ returns the result as an array. If its argument is an array, the
+ `atan' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+atanh
+
+ SYNOPSIS
+ Compute the inverse-tanh of an number
+
+ USAGE
+ y = atanh (x)
+
+ DESCRIPTION
+ The `atanh' function computes the inverse-tanh of a number and
+ returns the result as an array. If its argument is an array, the
+ `atanh' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+cos
+
+ SYNOPSIS
+ Compute the cosine of an number
+
+ USAGE
+ y = cos (x)
+
+ DESCRIPTION
+ The `cos' function computes the cosine of a number and
+ returns the result as an array. If its argument is an array, the
+ `cos' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+cosh
+
+ SYNOPSIS
+ Compute the hyperbolic cosine of an number
+
+ USAGE
+ y = cosh (x)
+
+ DESCRIPTION
+ The `cosh' function computes the hyperbolic cosine of a number and
+ returns the result as an array. If its argument is an array, the
+ `cosh' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+exp
+
+ SYNOPSIS
+ Compute the exponential of an number
+
+ USAGE
+ y = exp (x)
+
+ DESCRIPTION
+ The `exp' function computes the exponential of a number and
+ returns the result as an array. If its argument is an array, the
+ `exp' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+log
+
+ SYNOPSIS
+ Compute the logarithm of an number
+
+ USAGE
+ y = log (x)
+
+ DESCRIPTION
+ The `log' function computes the logarithm of a number and
+ returns the result as an array. If its argument is an array, the
+ `log' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+log10
+
+ SYNOPSIS
+ Compute the base-10 logarithm of an number
+
+ USAGE
+ y = log10 (x)
+
+ DESCRIPTION
+ The `log10' function computes the base-10 logarithm of a number and
+ returns the result as an array. If its argument is an array, the
+ `log10' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+mul2
+
+ SYNOPSIS
+ Multiply a number by 2
+
+ USAGE
+ y = mul2(x)
+
+ DESCRIPTION
+ The `mul2' function multiplies an arithmetic type by two and
+ returns the result. If its argument is an array, a new array will
+ be created whose elements are obtained from the original array by
+ using the `mul2' function.
+
+ SEE ALSO
+ sqr, abs
+--------------------------------------------------------------
+
+polynom
+
+ SYNOPSIS
+ Evaluate a polynomial
+
+ USAGE
+ Double_Type polynom(Double_Type a, b, ...c, Integer_Type n, Double_Type x)
+
+ DESCRIPTION
+ The `polynom' function returns the value of the polynomial expression:
+
+ ax^n + bx^(n - 1) + ... c
+
+
+ NOTES
+ The `polynom' function should be extended to work with complex
+ and array data types. The current implementation is limited to
+ `Double_Type' quantities.
+
+ SEE ALSO
+ exp
+--------------------------------------------------------------
+
+set_float_format
+
+ SYNOPSIS
+ Set the format for printing floating point values.
+
+ USAGE
+ set_float_format (String_Type fmt)
+
+ DESCRIPTION
+ The `set_float_format' function is used to set the floating
+ point format to be used when floating point numbers are printed.
+ The routines that use this are the traceback routines and the
+ `string' function. The default value is `"%f"'
+
+ EXAMPLE
+
+ s = string (PI); % --> s = "3.14159"
+ set_float_format ("%16.10f");
+ s = string (PI); % --> s = "3.1415926536"
+ set_float_format ("%10.6e");
+ s = string (PI); % --> s = "3.141593e+00"
+
+
+ SEE ALSO
+ string, sprintf, double
+--------------------------------------------------------------
+
+sign
+
+ SYNOPSIS
+ Compute the sign of a number
+
+ USAGE
+ y = sign(x)
+
+ DESCRIPTION
+ The `sign' function returns the sign of an arithmetic type. If
+ its argument is a complex number (`Complex_Type'), it returns
+ the sign of the imaginary part of the number. If the argument is an
+ array, a new array will be created whose elements are obtained from
+ the original array by using the `sign' function.
+
+ When applied to a real number or an integer, the `sign' function
+ returns -1, 0, or `+1' according to whether the number is
+ less than zero, equal to zero, or greater than zero, respectively.
+
+ SEE ALSO
+ abs
+--------------------------------------------------------------
+
+sin
+
+ SYNOPSIS
+ Compute the sine of an number
+
+ USAGE
+ y = sin (x)
+
+ DESCRIPTION
+ The `sin' function computes the sine of a number and
+ returns the result as an array. If its argument is an array, the
+ `sin' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+sinh
+
+ SYNOPSIS
+ Compute the hyperbolic sine of an number
+
+ USAGE
+ y = sinh (x)
+
+ DESCRIPTION
+ The `sinh' function computes the hyperbolic sine of a number and
+ returns the result as an array. If its argument is an array, the
+ `sinh' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+sqr
+
+ SYNOPSIS
+ Compute the square of a number
+
+ USAGE
+ y = sqr(x)
+
+ DESCRIPTION
+ The `sqr' function returns the square of an arithmetic type. If its
+ argument is a complex number (`Complex_Type'), then it returns
+ the square of the modulus. If the argument is an array, a new array
+ will be created whose elements are obtained from the original array
+ by using the `sqr' function.
+
+ SEE ALSO
+ abs, mul2
+--------------------------------------------------------------
+
+sqrt
+
+ SYNOPSIS
+ Compute the square root of an number
+
+ USAGE
+ y = sqrt (x)
+
+ DESCRIPTION
+ The `sqrt' function computes the square root of a number and
+ returns the result as an array. If its argument is an array, the
+ `sqrt' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ sqr, cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+tan
+
+ SYNOPSIS
+ Compute the tangent of an number
+
+ USAGE
+ y = tan (x)
+
+ DESCRIPTION
+ The `tan' function computes the tangent of a number and
+ returns the result as an array. If its argument is an array, the
+ `tan' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+tanh
+
+ SYNOPSIS
+ Compute the hyperbolic tangent of an number
+
+ USAGE
+ y = tanh (x)
+
+ DESCRIPTION
+ The `tanh' function computes the hyperbolic tangent of a number and
+ returns the result as an array. If its argument is an array, the
+ `tanh' function will be applied to each element and the result returned
+ as an array.
+
+ SEE ALSO
+ cos, atan, acosh, cosh
+--------------------------------------------------------------
+
+error
+
+ SYNOPSIS
+ Generate an error condition
+
+ USAGE
+ error (String_Type msg
+
+ DESCRIPTION
+ The `error' function generates a S-Lang error condition causing
+ the interpreter to start unwinding to top-level. It takes a single
+ string parameter which is displayed on the stderr output device.
+ The error condition may be cleared via an `ERROR_BLOCK' with the
+ `_clear_error' function. Consult \user-manual for more
+ information.
+
+ EXAMPLE
+
+ define add_txt_extension (file)
+ {
+ if (typeof (file) != String_Type)
+ error ("add_extension: parameter must be a string");
+ file += ".txt";
+ return file;
+ }
+
+
+ SEE ALSO
+ verror, _clear_error, message
+--------------------------------------------------------------
+
+message
+
+ SYNOPSIS
+ Print a string onto the message device
+
+ USAGE
+ message (String_Type s
+
+ DESCRIPTION
+ The `message' function will print the string specified by
+ `s' onto the message device.
+
+ EXAMPLE
+
+ define print_current_time ()
+ {
+ message (time ());
+ }
+
+
+ NOTES
+ The message device will depend upon the application. For example,
+ the output message device for the `jed' editor correspond to the
+ line at the bottom of the display window. The default message
+ device is the standard output device.
+
+ SEE ALSO
+ vmessage, sprintf, error
+--------------------------------------------------------------
+
+usage
+
+ SYNOPSIS
+ Generate a usage error
+
+ USAGE
+ usage (String_Type msg)
+
+ DESCRIPTION
+ The `usage' function generates a usage exception and displays
+ `msg' to the message device.
+
+ EXAMPLE
+ Suppose that some function `plot' plots an array of `x' and
+ `y' values. The such a function could be written to issue a
+ usage message if the wrong number of arguments were passed:
+
+ define plot ()
+ {
+ variable x, y;
+
+ if (_NARGS != 2)
+ usage ("plot (x, y)");
+
+ (x, y) = ();
+ % Now do the hard part
+ .
+ .
+ }
+
+
+ SEE ALSO
+ error, message
+--------------------------------------------------------------
+
+verror
+
+ SYNOPSIS
+ Generate an error condition
+
+ USAGE
+ verror (String_Type fmt, ...)
+
+ DESCRIPTION
+ The `verror' function performs the same role as the `error'
+ function. The only difference is that instead of a single string
+ argument, `verror' takes a sprintf style argument list.
+
+ EXAMPLE
+
+ define open_file (file)
+ {
+ variable fp;
+
+ fp = fopen (file, "r");
+ if (fp == NULL) verror ("Unable to open %s", file);
+ return fp;
+ }
+
+
+ NOTES
+ In the current implementation, strictly speaking, the `verror'
+ function is not an intrinsic function. Rather it is a predefined
+ S-Lang function using a combination of `Sprintf' and
+ `error'.
+
+ SEE ALSO
+ error, Sprintf, vmessage
+--------------------------------------------------------------
+
+vmessage
+
+ SYNOPSIS
+ Print a formatted string onto the message device
+
+ USAGE
+ vmessage (String_Type fmt, ...)
+
+ DESCRIPTION
+ The `vmessage' function formats a sprintf style argument list
+ and displays the resulting string onto the message device.
+
+ NOTES
+ In the current implementation, strictly speaking, the `vmessage'
+ function is not an intrinsic function. Rather it is a predefined
+ S-Lang function using a combination of `Sprintf' and
+ `message'.
+
+ SEE ALSO
+ message, Sprintf, verror
+--------------------------------------------------------------
+
+__class_id
+
+ SYNOPSIS
+ Return the class-id of a specified type
+
+ USAGE
+ Int_Type __class_id (DataType_Type type))
+
+ DESCRIPTION
+ This function returns the internal class-id of a specified data type.
+
+ SEE ALSO
+ typeof, _typeof, __class_type
+--------------------------------------------------------------
+
+__class_type
+
+ SYNOPSIS
+ Return the class-type of a specified type
+
+ USAGE
+ Int_Type __class_type (DataType_Type type))
+
+ DESCRIPTION
+ Internally S-Lang objects are classified according to four types:
+ scalar, vector, pointer, and memory managed types. For example, an
+ integer is implemented as a scalar, a complex number as a vector,
+ and a string is represented as a pointer. The `__class_type'
+ function returns an integer representing the class-type associated
+ with the specified data type. Specifically, it returns:
+
+ 0 memory-managed
+ 1 scalar
+ 2 vector
+ 3 pointer
+
+
+ SEE ALSO
+ typeof, _typeof, __class_id
+--------------------------------------------------------------
+
+__eqs
+
+ SYNOPSIS
+ Test for equality between two objects
+
+ USAGE
+ Int_Type __eqs (a, b)
+
+ DESCRIPTION
+ This function tests its two arguments for equalit and returns 1
+ if they are equal, and 0 otherwise. To be equal, the data type of
+ the arguments must match and the values of the objects must
+ reference the same underlying object.
+
+ EXAMPLE
+ __eqs (1, 1) ===> 1
+ __eqs (1, 1.0) ===> 0
+ __eqs ("a", 1) ===> 0
+ __eqs ([1,2], [1,2]) ===> 0
+
+ SEE ALSO
+ typeof, __get_reference
+
+ NOTES
+ This function should be thought of as a test for "sameness".
+--------------------------------------------------------------
+
+__get_reference
+
+ SYNOPSIS
+ Get a reference to a global object
+
+ USAGE
+ Ref_Type __get_reference (String_Type nm)
+
+ DESCRIPTION
+ This function returns a reference to a global variable or function
+ whose name is specified by `nm'. If no such object exists, it
+ returns `NULL', otherwise it returns a reference.
+
+ EXAMPLE
+ For example, consider the function:
+
+ define runhooks (hook)
+ {
+ variable f;
+ f = __get_reference (hook);
+ if (f != NULL)
+ @f ();
+ }
+
+ This function could be called from another S-Lang function to
+ allow customization of that function, e.g., if the function
+ represents a mode, the hook could be called to setup keybindings
+ for the mode.
+
+ SEE ALSO
+ is_defined, typeof, eval, autoload, __is_initialized, __uninitialize
+--------------------------------------------------------------
+
+__uninitialize
+
+ SYNOPSIS
+ Uninitialize a variable
+
+ USAGE
+ __uninitialize (Ref_Type x)
+
+ DESCRIPTION
+ The `__uninitialize' function may be used to uninitialize the
+ variable referenced by the parameter `x'.
+
+ EXAMPLE
+ The following two lines are equivalent:
+
+ () = __tmp(z);
+ __uninitialize (&z);
+
+
+ SEE ALSO
+ __tmp, __is_initialized
+--------------------------------------------------------------
+
+_auto_declare
+
+ SYNOPSIS
+ Set automatic variable declaration mode
+
+ USAGE
+ Integer_Type _auto_declare
+
+ DESCRIPTION
+ The `_auto_declare' may be used to have all undefined variables
+ implicitely declared as `static'. If set to zero, any variable
+ must be declared witha `variable' declaration before it can be
+ used. If set to one, then any undeclared variabled will be declared
+ as a `static' global variable.
+
+ The `_auto_declare' variable is local to each compilation unit and
+ setting its value in one unit has no effect upon its value in other
+ units. The value of this variable has no effect upon the variables
+ in a function.
+
+ EXAMPLE
+ The following code will not compile if `X' not been
+ declared:
+
+ X = 1;
+
+ However,
+
+ _auto_declare = 1; % declare variables as static.
+ X = 1;
+
+ is equivalent to
+
+ static variable X = 1;
+
+
+ NOTES
+ This variable should be used sparingly and is intended primarily for
+ interactive applications where one types S-Lang commands at a prompt.
+--------------------------------------------------------------
+
+current_namespace
+
+ SYNOPSIS
+ Get the name of the current namespace
+
+ USAGE
+ String_Type current_namespace ()
+
+ DESCRIPTION
+ The `current_namespace' function returns the name of the
+ current namespace. If the current namespace is anonymous, that is,
+ has not been given a name via the `implements' function, the
+ empty string `""' will be returned.
+
+ SEE ALSO
+ implements, use_namespace, import
+--------------------------------------------------------------
+
+getenv
+
+ SYNOPSIS
+ Get the value of an environment variable
+
+ USAGE
+ String_Type getenv(String_Type var)
+
+ DESCRIPTION
+ The `getenv' function returns a string that represents the
+ value of an environment variable `var'. It will return
+ `NULL' if there is no environment variable whose name is given
+ by `var'.
+
+ EXAMPLE
+
+ if (NULL != getenv ("USE_COLOR"))
+ {
+ set_color ("normal", "white", "blue");
+ set_color ("status", "black", "gray");
+ USE_ANSI_COLORS = 1;
+ }
+
+
+ SEE ALSO
+ putenv, strlen, is_defined
+--------------------------------------------------------------
+
+implements
+
+ SYNOPSIS
+ Name a private namespace
+
+ USAGE
+ implements (String_Type name);
+
+ DESCRIPTION
+ The `implements' function may be used to name the private
+ namespace associated with the current compilation unit. Doing so
+ will enable access to the members of the namespace from outside the
+ unit. The name of the global namespace is `Global'.
+
+ EXAMPLE
+ Suppose that some file `t.sl' contains:
+
+ implements ("Ts_Private");
+ static define message (x)
+ {
+ Global->vmessage ("Ts_Private message: %s", x);
+ }
+ message ("hello");
+
+ will produce `"Ts_Private message: hello"'. This `message'
+ function may be accessed from outside via:
+
+ Ts_Private->message ("hi");
+
+
+ NOTES
+ Since `message' is an intrinsic function, it is global and may
+ not be redefined in the global namespace.
+
+ SEE ALSO
+ use_namespace, current_namespace, import
+--------------------------------------------------------------
+
+putenv
+
+ SYNOPSIS
+ Add or change an environment variable
+
+ USAGE
+ putenv (String_Type s)
+
+ DESCRIPTION
+ This functions adds string `s' to the environment. Typically,
+ `s' should of the form `"name=value"'. The function
+ signals a S-Lang error upon failure.
+
+ NOTES
+ This function is not available on all systems.
+
+ SEE ALSO
+ getenv, sprintf
+--------------------------------------------------------------
+
+use_namespace
+
+ SYNOPSIS
+ Change to another namespace
+
+ USAGE
+ use_namespace (String_Type name)
+
+ DESCRIPTION
+ The `use_namespace' function changes the current namespace to
+ the one specified by the parameter. If the specified namespace
+ does not exist, an error will be generated.
+
+ SEE ALSO
+ implements, current_namespace, import
+--------------------------------------------------------------
+
+path_basename
+
+ SYNOPSIS
+ Get the basename part of a pathname
+
+ USAGE
+ String_Type path_basename (String_Type path)
+
+ DESCRIPTION
+ The `path_basename' function returns the basename associated
+ with the `path' parameter. The basename is the non-directory
+ part of the filename, e.g., on unix `c' is the basename of
+ `/a/b/c'.
+
+ SEE ALSO
+ path_dirname, path_extname, path_concat, path_is_absolute
+--------------------------------------------------------------
+
+path_concat
+
+ SYNOPSIS
+ Combine elements of a pathname
+
+ USAGE
+ String_Type path_concat (String_Type dir, String_Type basename)
+
+ DESCRIPTION
+ The `path_concat' function combines the arguments `dir' and
+ `basename' to produce a pathname. For example, on unix is
+ `dir' is `x/y' and `basename' is `z', then the
+ function will return `x/y/z'.
+
+ SEE ALSO
+ path_dirname, path_basename, path_extname, path_is_absolute
+--------------------------------------------------------------
+
+path_dirname
+
+ SYNOPSIS
+ Get the directory name part of a pathname
+
+ USAGE
+ String_Type path_dirname (String_Type path)
+
+ DESCRIPTION
+ The `path_dirname' function returns the directory name
+ associated with a specified pathname.
+
+ NOTES
+ On systems that include a drive specifier as part of the pathname,
+ the value returned by this function will include the driver
+ specifier.
+
+ SEE ALSO
+ path_basename, path_extname, path_concat, path_is_absolute
+--------------------------------------------------------------
+
+path_extname
+
+ SYNOPSIS
+ Return the extension part of a pathname
+
+ USAGE
+ String_Type path_extname (String_Type path)
+
+ DESCRIPTION
+ The `path_extname' function returns the extension portion of a
+ specified pathname. If an extension is present, this function will
+ also include the dot as part of the extension, i.e., if `path'
+ is `file.c', then this function returns `".c"'. If no
+ extension is present, the function returns an empty string `""'.
+
+ NOTES
+ Under VMS, the file version number is not returned as part of the
+ extension.
+
+ SEE ALSO
+ path_sans_extname, path_dirname, path_basename, path_concat, path_is_absolute
+--------------------------------------------------------------
+
+path_get_delimiter
+
+ SYNOPSIS
+ Get the value of a search-path delimiter
+
+ USAGE
+ Char_Type path_get_delimiter ()
+
+ DESCRIPTION
+ This function returns the value of the character used to delimit
+ fields of a search-path.
+
+ SEE ALSO
+ set_slang_load_path, get_slang_load_path
+--------------------------------------------------------------
+
+path_is_absolute
+
+ SYNOPSIS
+ Determine whether or not a pathname is absolute
+
+ USAGE
+ Int_Type path_is_absolute (String_Type path)
+
+ DESCRIPTION
+ The `path_is_absolute' function will return non-zero is
+ `path' refers to an absolute pathname, otherwise it returns zero.
+
+ SEE ALSO
+ path_dirname, path_basename, path_extname, path_concat
+--------------------------------------------------------------
+
+path_sans_extname
+
+ SYNOPSIS
+ Strip the extension from a pathname
+
+ USAGE
+ String_Type path_sans_extname (String_Type path)
+
+ DESCRIPTION
+ The `path_sans_extname' function removes the file name extension
+ (including the dot) from the path and returns the result.
+
+ SEE ALSO
+ path_extname, path_basename, path_dirname, path_concat
+--------------------------------------------------------------
+
+close
+
+ SYNOPSIS
+ Close an open file descriptor
+
+ USAGE
+ Int_Type close (FD_Type fd)
+
+ DESCRIPTION
+ The `close' function is used to open file descriptor of type
+ `FD_Type'. Upon success 0 is returned, otherwise the function
+ returns -1 and sets `errno' accordingly.
+
+ SEE ALSO
+ open, fclose, read, write
+--------------------------------------------------------------
+
+dup_fd
+
+ SYNOPSIS
+ Duplicate a file descriptor
+
+ USAGE
+ FD_Type dup_fd (FD_Type fd)
+
+ DESCRIPTION
+ The `dup_fd' function duplicates and file descriptor and returns
+ its duplicate. If the function fails, NULL will be returned and
+ `errno' set accordingly.
+
+ NOTES
+ This function is essentually a wrapper around the POSIX `dup'
+ function.
+
+ SEE ALSO
+ open, close
+--------------------------------------------------------------
+
+fileno
+
+ SYNOPSIS
+ Convert a stdio File_Type object to a FD_Type descriptor
+
+ USAGE
+ FD_Type fileno (File_Type fp)
+
+ DESCRIPTION
+ The `fileno' function returns the `FD_Type' descriptor
+ associated with the `File_Type' file pointer. Upon failure,
+ NULL is returned.
+
+ SEE ALSO
+ fopen, open, fclose, close, dup_fd
+--------------------------------------------------------------
+
+isatty
+
+ SYNOPSIS
+ Determine if an open file descriptor refers to a terminal
+
+ USAGE
+ Int_Type isatty (FD_Type or File_Type fd)
+
+ DESCRIPTION
+ This function returns 1 if the file descriptor `fd' refers to a
+ terminal; otherwise it returns 0. The object `fd' may either
+ be a `File_Type' stdio descriptor or an `FD_Type' object.
+
+ SEE ALSO
+ fopen, fclose, fileno
+--------------------------------------------------------------
+
+lseek
+
+ SYNOPSIS
+ Reposition a file descriptor's file pointer
+
+ USAGE
+ Long_Type lseek (FD_Type fd, Long_Type ofs, int mode)
+
+ SEEK_SET Set the offset to ofs
+ SEEK_CUR Add ofs to the current offset
+ SEEK_END Add ofs to the current file size
+
+
+ NOTES
+ Not all file descriptors are capable of supporting the seek
+ operation, e.g., a descriptor associated with a pipe.
+
+ By using `SEEK_END' with a positive value of the `ofs'
+ parameter, it is possible to position the file pointer beyond the
+ current size of the file.
+
+ SEE ALSO
+ fseek, ftell, open, close
+--------------------------------------------------------------
+
+open
+
+ SYNOPSIS
+ Open a file
+
+ USAGE
+ FD_Type open (String_Type filename, Int_Type flags [,Int_Type mode])
+
+ DESCRIPTION
+ The `open' function attempts to open a file specified by the
+ `filename' parameter according to the `flags' parameter,
+ which must be one of the following values:
+
+ O_RDONLY (read-only)
+ O_WRONLY (write-only)
+ O_RDWR (read/write)
+
+ In addition, `flags' may also be bitwise-or'd with any of the
+ following:
+
+ O_BINARY (open the file in binary mode)
+ O_TEXT (open the file in text mode)
+ O_CREAT (create file if it does not exist)
+ O_EXCL (fail if the file already exists)
+ O_NOCTTY (do not make the device the controlling terminal)
+ O_TRUNC (truncate the file if it exists)
+ O_APPEND (open the file in append mode)
+ O_NONBLOCK (open the file in non-blocking mode)
+
+ Some of these flags only make sense when combined with other flags.
+ For example, if O_EXCL is used, then O_CREAT must also be
+ specified, otherwise unpredictable behavior may result.
+
+ If `O_CREAT' is used for the `flags' parameter then the
+ `mode' parameter must be present. `mode' specifies the
+ permissions to use if a new file is created. The actual file
+ permissions will be affected by the process's `umask' via
+ `mode&~umask'. The `mode' parameter's value is
+ constructed via bitwise-or of the following values:
+
+ S_IRWXU (Owner has read/write/execute permission)
+ S_IRUSR (Owner has read permission)
+ S_IWUSR (Owner has write permission)
+ S_IXUSR (Owner has execute permission)
+ S_IRWXG (Group has read/write/execute permission)
+ S_IRGRP (Group has read permission)
+ S_IWGRP (Group has write permission)
+ S_IXGRP (Group has execute permission)
+ S_IRWXO (Others have read/write/execute permission)
+ S_IROTH (Others have read permission)
+ S_IWOTH (Others have write permission)
+ S_IXOTH (Others have execute permission)
+
+ Upon success `open' returns a file descriptor object
+ (`FD_Type'), otherwise `NULL' is returned and `errno'
+ is set.
+
+ NOTES
+ If you are not familiar with the `open' system call, then it
+ is recommended that you use `fopen' instead.
+
+ SEE ALSO
+ fopen, close, read, write, stat_file
+--------------------------------------------------------------
+
+read
+
+ SYNOPSIS
+ Read from an open file descriptor
+
+ USAGE
+ UInt_Type read (FD_Type fd, Ref_Type buf, UInt_Type num)
+
+ DESCRIPTION
+ The `read' function attempts to read at most `num' bytes
+ into the variable indicated by `buf' from the open file
+ descriptor `fd'. It returns the number of bytes read, or -1
+ and sets `errno' upon failure. The number of bytes read may be
+ less than `num', and will be zero if an attempt is made to read
+ past the end of the file.
+
+ NOTES
+ `read' is a low-level function and may return -1 for a variety
+ of reasons. For example, if non-blocking I/O has been specified for
+ the open file descriptor and no data is available for reading then
+ the function will return -1 and set `errno' to `EAGAIN'.
+
+ SEE ALSO
+ fread, open, close, write
+--------------------------------------------------------------
+
+write
+
+ SYNOPSIS
+ Write to an open file descriptor
+
+ USAGE
+ UInt_Type write (FD_Type fd, BString_Type buf)
+
+ DESCRIPTION
+ The `write' function attempts to write the bytes specified by
+ the `buf' parameter to the open file descriptor `fd'. It
+ returns the number of bytes successfully written, or -1 and sets
+ `errno' upon failure. The number of bytes written may be less
+ than `length(buf)'.
+
+ SEE ALSO
+ read, fwrite, open, close
+--------------------------------------------------------------
+
+errno
+
+ SYNOPSIS
+ Error code set by system functions.
+
+ USAGE
+ Integer_Type errno
+
+ DESCRIPTION
+ A system function can fail for a variety of reasons. For example, a
+ file operation may fail because lack of disk space, or the process
+ does not have permission to perform the operation. Such functions
+ will return `-1' and set the variable `errno' to an error
+ code describing the reason for failure.
+
+ Particular values of `errno' may be specified by the following
+ symbolic constants (read-only variables) and the corresponding
+ `errno_string' value:
+
+ EPERM "Not owner"
+ ENOENT "No such file or directory"
+ ESRCH "No such process"
+ ENXIO "No such device or address"
+ ENOEXEC "Exec format error"
+ EBADF "Bad file number"
+ ECHILD "No children"
+ ENOMEM "Not enough core"
+ EACCES "Permission denied"
+ EFAULT "Bad address"
+ ENOTBLK "Block device required"
+ EBUSY "Mount device busy"
+ EEXIST "File exists"
+ EXDEV "Cross-device link"
+ ENODEV "No such device"
+ ENOTDIR "Not a directory"
+ EISDIR "Is a directory"
+ EINVAL "Invalid argument"
+ ENFILE "File table overflow"
+ EMFILE "Too many open files"
+ ENOTTY "Not a typewriter"
+ ETXTBSY "Text file busy"
+ EFBIG "File too large"
+ ENOSPC "No space left on device"
+ ESPIPE "Illegal seek"
+ EROFS "Read-only file system"
+ EMLINK "Too many links"
+ EPIPE "Broken pipe"
+ ELOOP "Too many levels of symbolic links"
+ ENAMETOOLONG "File name too long"
+
+
+ EXAMPLE
+ The `mkdir' function will attempt to create a directory. If
+ that directory already exists, the function will fail and set
+ `errno' to `EEXIST'.
+
+ define create_dir (dir)
+ {
+ if (0 == mkdir (dir)) return;
+ if (errno != EEXIST)
+ error ("mkdir %s failied: %s", dir, errno_string);
+ }
+
+
+ SEE ALSO
+ errno_string, error, mkdir
+--------------------------------------------------------------
+
+errno_string
+
+ SYNOPSIS
+ Return a string describing an errno.
+
+ USAGE
+ String_Type errno_string (Integer_Type err)
+
+ DESCRIPTION
+ The `errno_string' function returns a string describing the
+ integer error code `err'. The variable `err' usually
+ corresponds to the `errno' intrinsic function. See the
+ description for `errno' for more information.
+
+ EXAMPLE
+ The `errno_string' function may be used as follows:
+
+ define sizeof_file (file)
+ {
+ variable st = stat (file);
+ if (st == NULL)
+ verror ("%s: %s", file, errno_string (errno);
+ return st.st_size;
+ }
+
+
+ SEE ALSO
+ errno, stat, verror
+--------------------------------------------------------------
+
+getegid
+
+ SYNOPSIS
+ Get the effective group id
+
+ USAGE
+ Int_Type getegid ()
+
+ DESCRIPTION
+ The `getegid' function returns the effective group ID of the
+ current process.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getgid, geteuid, setgid
+--------------------------------------------------------------
+
+geteuid
+
+ SYNOPSIS
+ Get the effective user-id of the current process
+
+ USAGE
+ Int_Type geteuid ()
+
+ DESCRIPTION
+ The `geteuid' function returns the effective user-id of the
+ current process.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getuid, setuid, setgid
+--------------------------------------------------------------
+
+getgid
+
+ SYNOPSIS
+ Get the group id
+
+ USAGE
+ Integer_Type getgid ()
+
+ DESCRIPTION
+ The `getgid' function returns the real group id of the current
+ process.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getpid, getppid
+--------------------------------------------------------------
+
+getpid
+
+ SYNOPSIS
+ Get the current process id
+
+ USAGE
+ Integer_Type getpid ()
+
+ DESCRIPTION
+ The `getpid' function returns the current process identification
+ number.
+
+ SEE ALSO
+ getppid, getgid
+--------------------------------------------------------------
+
+getppid
+
+ SYNOPSIS
+ Get the parent process id
+
+ USAGE
+ Integer_Type getppid ()
+
+ DESCRIPTION
+ The `getpid' function returns the process identification
+ number of the parent process.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getpid, getgid
+--------------------------------------------------------------
+
+getuid
+
+ SYNOPSIS
+ Get the user-id of the current process
+
+ USAGE
+ Int_Type getuid ()
+
+ DESCRIPTION
+ The `getuid' function returns the user-id of the current
+ process.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getuid, getegid
+--------------------------------------------------------------
+
+kill
+
+ SYNOPSIS
+ Send a signal to a process
+
+ USAGE
+ Integer_Type kill (Integer_Type pid, Integer_Type sig)
+
+ DESCRIPTION
+ This function may be used to send a signal given by the integer `sig'
+ to the process specified by `pid'. The function returns zero upon
+ success and `-1' upon failure setting errno accordingly.
+
+ EXAMPLE
+ The `kill' function may be used to determine whether or not
+ a specific process exists:
+
+ define process_exists (pid)
+ {
+ if (-1 == kill (pid, 0))
+ return 0; % Process does not exist
+ return 1;
+ }
+
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getpid
+--------------------------------------------------------------
+
+mkfifo
+
+ SYNOPSIS
+ Create a named pipe
+
+ USAGE
+ Int_Type mkfifo (String_Type name, Int_Type mode)
+
+ DESCRIPTION
+ The `mkfifo' attempts to create a named pipe with the specified
+ name and mode (modified by the process's umask). The function
+ returns 0 upon success, or -1 and sets `errno' upon failure.
+
+ NOTES
+ Not all systems support the `mkfifo' function and even on
+ systems that do implement the `mkfifo' system call, the
+ underlying file system may not support the concept of a named pipe,
+ e.g, an NFS filesystem.
+
+ SEE ALSO
+ stat_file
+--------------------------------------------------------------
+
+setgid
+
+ SYNOPSIS
+ Set the group-id of the current process
+
+ USAGE
+ Int_Type setgid (Int_Type gid)
+
+ DESCRIPTION
+ The `setgid' function sets the effective group-id of the current
+ process. It returns zero upon success, or -1 upon error and sets
+ `errno' appropriately.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ getgid, setuid
+--------------------------------------------------------------
+
+setpgid
+
+ SYNOPSIS
+ Set the process group-id
+
+ USAGE
+ Int_Type setpgid (Int_Type pid, Int_Type gid)
+
+ DESCRIPTION
+ The `setpgid' function sets the group-id `gid' of the
+ process whose process-id is `pid'. If `pid' is 0, then the
+ current process-id will be used. If `pgid' is 0, then the pid
+ of the affected process will be used.
+
+ If successful zero will be returned, otherwise the function will
+ return -1 and set `errno' accordingly.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ setgid, setuid
+--------------------------------------------------------------
+
+setuid
+
+ SYNOPSIS
+ Set the user-id of the current process
+
+ USAGE
+ Int_Type setuid (Int_Type id)
+
+ DESCRIPTION
+ The `setuid' function sets the effective user-id of the current
+ process. It returns zero upon success, or -1 upon error and sets
+ `errno' appropriately.
+
+ NOTES
+ This function is not supported by all systems.
+
+ SEE ALSO
+ setgid, setpgid, getuid, geteuid
+--------------------------------------------------------------
+
+sleep
+
+ SYNOPSIS
+ Pause for a specified number of seconds
+
+ USAGE
+ sleep (Double_Type n)
+
+ DESCRIPTION
+ The `sleep' function delays the current process for the
+ specified number of seconds. If it is interrupted by a signal, it
+ will return prematurely.
+
+ NOTES
+ Not all system support sleeping for a fractional part of a second.
+--------------------------------------------------------------
+
+system
+
+ SYNOPSIS
+ Execute a shell command
+
+ USAGE
+ Integer_Type system (String_Type cmd)
+
+ DESCRIPTION
+ The `system' function may be used to execute the string
+ expression `cmd' in an inferior shell. This function is an
+ interface to the C `system' function which returns an
+ implementation-defined result. On Linux, it returns 127 if the
+ inferior shell could not be invoked, -1 if there was some other
+ error, otherwise it returns the return code for `cmd'.
+
+ EXAMPLE
+
+ define dir ()
+ {
+ () = system ("DIR");
+ }
+
+ displays a directory listing of the current directory under MSDOS or
+ VMS.
+
+ SEE ALSO
+ popen, listdir
+--------------------------------------------------------------
+
+umask
+
+ SYNOPSIS
+ Set the file creation mask
+
+ USAGE
+ Int_Type umask (Int_Type m)
+
+ DESCRIPTION
+ The `umask' function sets the file creation mask to `m' and
+ returns the previous mask.
+
+ SEE ALSO
+ stat_file
+--------------------------------------------------------------
+
+uname
+
+ SYNOPSIS
+ Get the system name
+
+ USAGE
+ Struct_Tye uname ()
+
+ DESCRIPTION
+ The `uname' function returns a structure containing information
+ about the operating system. The structure contains the following
+ fields:
+
+ sysname (Name of the operating system)
+ nodename (Name of the node within the network)
+ release (Release level of the OS)
+ version (Current version of the release)
+ machine (Name of the hardware)
+
+
+ NOTES
+ Not all systems support this function.
+
+ SEE ALSO
+ getenv, pack, unpack
+--------------------------------------------------------------
+
+__pop_args
+
+ SYNOPSIS
+ Remove n function arguments from the stack
+
+ USAGE
+ variable args = __pop_args(Integer_Type n);
+
+ DESCRIPTION
+ This function together with the companion function `__push_args'
+ is useful for passing the arguments of a function to another function.
+ `__pop_args' returns an array of `n' structures with a
+ single structure field called `value', which represents the value
+ of the argument.
+
+ EXAMPLE
+ Consider the following `print' function. It prints all its
+ arguments to `stdout' separated by spaces:
+
+ define print ()
+ {
+ variable i;
+ variable args = __pop_args (_NARGS);
+
+ for (i = 0; i < _NARGS; i++)
+ {
+ () = fputs (string (args[i].value), stdout);
+ () = fputs (" ", stdout);
+ }
+ () = fputs ("\n", stdout);
+ () = fflush (stdout);
+ }
+
+ Now consider the problem of defining a function called `ones'
+ that returns a multi-dimensional array with all the elements set to
+ 1. For example, `ones(10)' should return a 1-d array of ones,
+ whereas `ones(10,20)' should return a 10x20 array.
+
+ define ones ()
+ {
+ !if (_NARGS) return 1;
+ variable a;
+
+ a = __pop_args (_NARGS);
+ return @Array_Type (Integer_Type, [__push_args (a)]) + 1;
+ }
+
+ Here, `__push_args' was used to push on the arguments passed to
+ the `ones' function onto the stack to be used when dereferencing
+ `Array_Type'.
+
+ SEE ALSO
+ __push_args, typeof, _pop_n
+--------------------------------------------------------------
+
+__push_args
+
+ SYNOPSIS
+ Remove n function arguments onto the stack
+
+ USAGE
+ __push_args (Struct_Type args);
+
+ DESCRIPTION
+ This function together with the companion function `__pop_args'
+ is useful for passing the arguments of one function to another.
+ See the desription of `__pop_args' for more information.
+
+ SEE ALSO
+ __pop_args, typeof, _pop_n
+--------------------------------------------------------------
+
+_pop_n
+
+ SYNOPSIS
+ Remove objects from the stack
+
+ USAGE
+ _pop_n (Integer_Type n);
+
+ DESCRIPTION
+ The `_pop_n' function pops `n' objects from the top of the
+ stack.
+
+ EXAMPLE
+
+ define add3 ()
+ {
+ variable x, y, z;
+ if (_NARGS != 3)
+ {
+ _pop_n (_NARGS);
+ error ("add3: Expecting 3 arguments");
+ }
+ (x, y, z) = ();
+ return x + y + z;
+ }
+
+
+ SEE ALSO
+ _stkdepth, pop
+--------------------------------------------------------------
+
+_print_stack
+
+ SYNOPSIS
+ print the values on the stack.
+
+ USAGE
+ _print_stack ()
+
+ DESCRIPTION
+ This function dumps out what is currently on the S-Lang. It does not
+ alter the stack and it is usually used for debugging purposes.
+
+ SEE ALSO
+ _stkdepth, string
+--------------------------------------------------------------
+
+_stk_reverse
+
+ SYNOPSIS
+ Reverse the order of the objects on the stack.
+
+ USAGE
+ _stk_reverse (Integer_Type n)
+
+ DESCRIPTION
+ The `_stk_reverse' function reverses the order of the top
+ `n' items on the stack.
+
+ SEE ALSO
+ _stkdepth, _stk_roll
+--------------------------------------------------------------
+
+_stk_roll
+
+ SYNOPSIS
+ Roll items on the stack
+
+ USAGE
+ _stk_roll (Integer_Type n);
+
+ DESCRIPTION
+ This function may be used to alter the arrangement of objects on the
+ stack. Specifically, if the integer `n' is positive, the top
+ `n' items on the stack are rotated up. If
+ `n' is negative, the top `abs(n)' items on the stack are
+ rotated down.
+
+ EXAMPLE
+ If the stack looks like:
+
+ item-0
+ item-1
+ item-2
+ item-3
+
+ where `item-0' is at the top of the stack, then
+ `_stk_roll(-3)' will change the stack to:
+
+ item-2
+ item-0
+ item-1
+ item-3
+
+
+ NOTES
+ This function only has an effect for `abs(n) > 1'.
+
+ SEE ALSO
+ _stkdepth, _stk_reverse, _pop_n, _print_stack
+--------------------------------------------------------------
+
+_stkdepth
+
+ USAGE
+ Get the number of objects currently on the stack.
+
+ SYNOPSIS
+ Integer_Type _stkdepth ()
+
+ DESCRIPTION
+ The `_stkdepth' function returns number of items on stack prior
+ to the call of `_stkdepth'.
+
+ SEE ALSO
+ _print_stack, _stk_reverse, _stk_roll
+--------------------------------------------------------------
+
+dup
+
+ SYNOPSIS
+ Duplicate the value at the top of the stack
+
+ USAGE
+ dup ()
+
+ DESCRIPTION
+ This function returns an exact duplicate of the object on top of the
+ stack. For some objects such as arrays or structures, it creates a
+ new reference to the array. However, for simple scalar S-Lang types such
+ as strings, integers, and doubles, it creates a new copy of the
+ object.
+
+ SEE ALSO
+ pop, typeof
+--------------------------------------------------------------
+
+exch
+
+ SYNOPSIS
+ Exchange two items on the stack
+
+ USAGE
+ exch ()
+
+ DESCRIPTION
+ The `exch' swaps the two top items on the stack.
+
+ SEE ALSO
+ pop, _stk_reverse, _stk_roll
+--------------------------------------------------------------
+
+pop
+
+ SYNOPSIS
+ Discard an item from the stack
+
+ USAGE
+ pop ()
+
+ DESCRIPTION
+ The `pop' function removes the top item from the stack.
+
+ SEE ALSO
+ _pop_n
+--------------------------------------------------------------
+
+clearerr
+
+ SYNOPSIS
+ Clear the error of a file stream
+
+ USAGE
+ clearerr (File_Type fp
+
+ DESCRIPTION
+ The `clearerr' function clears the error and end-of-file flags
+ associated with the open file stream `fp'.
+
+ SEE ALSO
+ ferror, feof, fopen
+--------------------------------------------------------------
+
+fclose
+
+ SYNOPSIS
+ Close a file
+
+ USAGE
+ Integer_Type fclose (File_Type fp)
+
+ DESCRIPTION
+ The `fclose' function may be used to close an open file pointer
+ `fp'. Upon success it returns zero, and upon failure it sets
+ `errno' and returns `-1'. Failure usually indicates a that
+ the file system is full or that `fp' does not refer to an open file.
+
+ NOTES
+ Many C programmers call `fclose' without checking the return
+ value. The S-Lang language requires the programmer to explicitly
+ handle any value returned by a S-Lang function. The simplest way to
+ handle the return value from `fclose' is to use it as:
+
+ () = fclose (fp);
+
+
+ SEE ALSO
+ fopen, fgets, fflush, pclose, errno
+--------------------------------------------------------------
+
+fdopen
+
+ SYNOPSIS
+ Convert a FD_Type file descriptor to a stdio File_Type object
+
+ USAGE
+ File_Type fdopen (FD_Type, String_Type mode)
+
+ DESCRIPTION
+ The `fdopen' function creates and returns a stdio
+ `File_Type' object from the open `FD_Type'
+ descriptor `fd'. The `mode' parameter corresponds to the
+ `mode' parameter of the `fopen' function and must be
+ consistent with the mode of the descriptor `fd'. The function
+ returns NULL upon failure and sets `errno'.
+
+ NOTES
+ The `fclose' function does not close the `File_Type' object
+ returned from this function. The underlying file object must be
+ closed by the `close' function.
+
+ SEE ALSO
+ fileno, fopen, open, close, fclose
+--------------------------------------------------------------
+
+feof
+
+ SYNOPSIS
+ Get the end-of-file status
+
+ USAGE
+ Integer_Type feof (File_Type fp)
+
+ DESCRIPTION
+ This function may be used to determine the state of the end-of-file
+ indicator of the open file descriptor `fp'. It returns `0'
+ if the indicator is not set, or non-zero if it is. The end-of-file
+ indicator may be cleared by the `clearerr' function.
+
+ SEE ALSO
+ ferror, clearerr, fopen
+--------------------------------------------------------------
+
+ferror
+
+ SYNOPSIS
+ Determine the error status of an open file descriptor
+
+ USAGE
+ Integer_Type ferror (File_Type fp)
+
+ DESCRIPTION
+ This function may be used to determine the state of the error
+ indicator of the open file descriptor `fp'. It returns `0'
+ if the indicator is not set, or non-zero if it is. The error
+ indicator may be cleared by the `clearerr' function.
+
+ SEE ALSO
+ feof, clearerr, fopen
+--------------------------------------------------------------
+
+fflush
+
+ SYNOPSIS
+ Flush an output stream
+
+ USAGE
+ Integer_Type fflush (File_Type fp)
+
+ DESCRIPTION
+ The `fflush' function may be used to update the _output_
+ stream specified by `fp'. It returns `0' upon success, or
+ `-1' upon failure and sets `errno' accordingly. In
+ particular, this function will fail if `fp' does not represent
+ an output stream, or if `fp' is associated with a disk file and
+ there is insufficient disk space.
+
+ EXAMPLE
+ This example illustrates how to use the `fflush' function
+ without regard to the return value:
+
+ () = fputs ("Enter value> ", stdout);
+ () = fflush (stdout);
+
+
+ NOTES
+ Many C programmers disregard the return value from the `fflush'
+ function. The above example illustrates how to properly do this in
+ the S-Lang langauge.
+
+ SEE ALSO
+ fopen, fclose
+--------------------------------------------------------------
+
+fgets
+
+ SYNOPSIS
+ Read a line from a file.
+
+ USAGE
+ Integer_Type fgets (SLang_Ref_Type ref, File_Type fp)
+
+ DESCRIPTION
+ `fgets' reads a line from the open file specified by `fp'
+ and places the characters in the variable whose reference is
+ specified by `ref'.
+ It returns `-1' if `fp' is not associated with an open file
+ or an attempt was made to read at the end the file; otherwise, it
+ returns the number of characters read.
+
+ EXAMPLE
+ The following example returns the lines of a file via a linked list:
+
+ define read_file (file)
+ {
+ variable buf, fp, root, tail;
+ variable list_type = struct { text, next };
+
+ root = NULL;
+
+ fp = fopen(file, "r");
+ if (fp == NULL)
+ error("fopen %s failed." file);
+ while (-1 != fgets (&buf, fp))
+ {
+ if (root == NULL)
+ {
+ root = @list_type;
+ tail = root;
+ }
+ else
+ {
+ tail.next = @list_type;
+ tail = tail.next;
+ }
+ tail.text = buf;
+ tail.next = NULL;
+ }
+ () = fclose (fp);
+ return root;
+ }
+
+
+ SEE ALSO
+ fopen, fclose, fputs, fread, error
+--------------------------------------------------------------
+
+fgetslines
+
+ SYNOPSIS
+ Read all the lines from an open file
+
+ USAGE
+ String_Type[] fgetslines (File_Type fp)
+
+ DESCRIPTION
+ The `fgetslines' function returns all the remaining lines as an
+ array of strings in the file specified by the open file pointer
+ `fp'. If the file is empty, an empty string array will be
+ returned. The function returns `NULL' upon error.
+
+ EXAMPLE
+ The following function returns the number of lines in a file:
+
+ define count_lines_in_file (file)
+ {
+ variable fp, lines;
+
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ return -1;
+
+ lines = fgetslines (fp);
+ if (lines == NULL)
+ return -1;
+
+ return length (lines);
+ }
+
+ Note that the file was implicitly closed by the function.
+
+ NOTES
+ This function should not be used if the file contains many lines
+ since that would require that all the lines be read into memory.
+
+ SEE ALSO
+ fgets, fread, fopen
+--------------------------------------------------------------
+
+fopen
+
+ SYNOPSIS
+ Open a file
+
+ USAGE
+ File_Type fopen (String_Type f, String_Type m)
+
+ DESCRIPTION
+ The `fopen' function opens a file `f' according to the mode
+ string `m'. Allowed values for `m' are:
+
+ "r" Read only
+ "w" Write only
+ "a" Append
+ "r+" Reading and writing at the beginning of the file.
+ "w+" Reading and writing. The file is created if it does not
+ exist; otherwise, it is truncated.
+ "a+" Reading and writing at the end of the file. The file is created
+ if it does not already exist.
+
+ In addition, the mode string can also include the letter `'b''
+ as the last character to indicate that the file is to be opened in
+ binary mode.
+
+ Upon success, `fopen' a `File_Type' object which is meant to
+ be used in other operations that require an open file. Upon
+ failure, the function returns `NULL'.
+
+ EXAMPLE
+ The following function opens a file in append mode and writes a
+ string to it:
+
+ define append_string_to_file (file, str)
+ {
+ variable fp = fopen (file, "a");
+ if (fp == NULL) verror ("%s could not be opened", file);
+ () = fputs (string, fp);
+ () = fclose (fp);
+ }
+
+ Note that the return values from `fputs' and `fclose' are
+ ignored.
+
+ NOTES
+ There is no need to explicitly close a file opened with `fopen'.
+ If the returned `File_Type' object goes out of scope, S-Lang
+ will automatically close the file. However, explicitly closing a
+ file after use is recommended.
+
+ SEE ALSO
+ fclose, fgets, fputs, popen
+--------------------------------------------------------------
+
+fprintf
+
+ SYNOPSIS
+ Create and write a formatted string to a file
+
+ USAGE
+ Int_Type fprintf (File_Type fp, String_Type fmt, ...)
+
+ DESCRIPTION
+ `fprintf' formats the objects specified by the variable argument
+ list according to the format `fmt' and write the result to the
+ open file pointer `fp'.
+
+ The format string obeys the same syntax and semantics as the
+ `sprintf' format string. See the description of the
+ `sprintf' function for more information.
+
+ `fprintf' returns the number of characters written to the file,
+ or -1 upon error.
+
+ SEE ALSO
+ fputs, printf, fwrite, message
+--------------------------------------------------------------
+
+fputs
+
+ SYNOPSIS
+ Write a string to an open stream
+
+ USAGE
+ Integer_Type fputs (String_Type s, File_Type fp);
+
+ DESCRIPTION
+ The `fputs' function writes the string `s' to the open file
+ pointer `fp'. It returns -1 upon failure and sets `errno',
+ otherwise it returns the length of the string.
+
+ EXAMPLE
+ The following function opens a file in append mode and uses the
+ `fputs' function to write to it.
+
+ define append_string_to_file (str, file)
+ {
+ variable fp;
+ fp = fopen (file, "a");
+ if (fp == NULL) verror ("Unable to open %s", file);
+ if ((-1 == fputs (s, fp))
+ or (-1 == fclose (fp)))
+ verror ("Error writing to %s", file);
+ }
+
+
+ NOTES
+ One must not disregard the return value from the `fputs'
+ function, as many C programmers do. Doing so may lead to a stack
+ overflow error.
+
+ To write an object that contains embedded null characters, use the
+ `fwrite' function.
+
+ SEE ALSO
+ fclose, fopen, fgets, fwrite
+--------------------------------------------------------------
+
+fread
+
+ SYNOPSIS
+ Read binary data from a file
+
+ USAGE
+ UInt_Type fread (Ref_Type b, DataType_Type t, UInt_Type n, File_Type fp)
+
+ DESCRIPTION
+ The `fread' function may be used to read `n' objects of type
+ `t' from an open file pointer `fp'. Upon success, it
+ returns the number of objects read from the file and places the
+ objects in the variable specified by `b'. Upon error or end of
+ file, it returns `-1'. If more than one object is read from the
+ file, those objects will be placed in an array of the appropriate
+ size. The exception to this is when reading `Char_Type' or
+ `UChar_Type' objects from a file, in which case the data will be
+ returned as an `n' character BString_Type binary string, but
+ only if `n'>1.
+
+ EXAMPLE
+ The following example illustrates how to read 50 bytes from a file:
+
+ define read_50_bytes_from_file (file)
+ {
+ variable fp, n, buf;
+
+ fp = fopen (file, "rb");
+ if (fp == NULL) error ("Open failed");
+ n = fread (&buf, Char_Type, 50, fp);
+ if (n == -1)
+ error ("fread failed");
+ () = fclose (fp);
+ return buf;
+ }
+
+
+ NOTES
+ Use the `pack' and `unpack' functions to read data with a
+ specific byte-ordering.
+
+ SEE ALSO
+ fwrite, fgets, fopen, pack, unpack
+--------------------------------------------------------------
+
+fseek
+
+ SYNOPSIS
+ Reposition a stream
+
+ USAGE
+ Integer_Type fseek (File_Type fp, Integer_Type ofs, Integer_Type whence
+
+ DESCRIPTION
+ The `fseek' function may be used to reposition the file position
+ pointer associated with the open file stream `fp'. Specifically,
+ it moves the pointer `ofs' bytes relative to the position
+ indicated by `whence'. If whence is set to one of the symbolic
+ constants `SEEK_SET', `SEEK_CUR', or `SEEK_END', the
+ offset is relative to the start of the file, the current position
+ indicator, or end-of-file, respectively.
+
+ The function return zero upon success, or -1 upon failure and sets
+ `errno' accordingly.
+
+ EXAMPLE
+ define rewind (fp)
+ {
+ if (0 == fseek (fp, 0, SEEK_SET)) return;
+ vmessage ("rewind failed, reason: %s", errno_string (errno));
+ }
+
+ NOTES
+ The current implementation uses an integer to specify the offset.
+ One some systems, a long integer may be required making this
+ function fail for very large files, i.e., files that are longer than
+ the maximum value of an integer.
+
+ SEE ALSO
+ ftell, fopen
+--------------------------------------------------------------
+
+ftell
+
+ SYNOPSIS
+ Obtain the current position in an open stream
+
+ USAGE
+ Integer_Type ftell (File_Type fp)
+
+ DESCRIPTION
+ The ftell function may be used to obtain the current position in the
+ stream associated with the open file pointer `fp'. It returns
+ the position of the pointer measured in bytes from the beginning of
+ the file. Upon error, it returns `-1' and sets `errno'.
+
+ SEE ALSO
+ fseek, fopen
+--------------------------------------------------------------
+
+fwrite
+
+ SYNOPSIS
+ Write binary data to a file
+
+ USAGE
+ UInt_Type fwrite (b, File_Type fp)
+
+ DESCRIPTION
+ The `fwrite' may be used to write the object represented by
+ `b' to an open file. If `b' is a string or an array, the
+ function will attempt to write all elements of the object to the
+ file. It returns the number of objects successfully written,
+ otherwise it returns -1 upon error and sets `errno'
+ accordingly.
+
+ EXAMPLE
+ The following example illustrates how to write an integer array to a
+ file. In this example, `fp' is an open file descriptor:
+
+ variable a = [1:50]; % 50 element integer array
+ if (50 != fwrite (a, fp))
+ error ("fwrite failed");
+
+ Here is how to write the array one element at a time:
+
+ variable a = [1:50];
+ foreach (a)
+ {
+ variable ai = ();
+ if (1 != fwrite(ai, fp))
+ error ("fwrite failed");
+ }
+
+
+ NOTES
+ Not all data types may support the `fwrite' operation. However,
+ it is supported by all vector, scalar, and string objects.
+
+ SEE ALSO
+ fread, fputs, fopen, pack, unpack
+--------------------------------------------------------------
+
+pclose
+
+ SYNOPSIS
+ Close an object opened with popen
+
+ USAGE
+ Integer_Type pclose (File_Type fp)
+
+ DESCRIPTION
+ The `pclose' function waits for the process associated with
+ `fp' to exit and the returns the exit status of the command.
+
+ SEE ALSO
+ pclose, fclose
+--------------------------------------------------------------
+
+popen
+
+ SYNOPSIS
+ Open a process
+
+ USAGE
+ File_Type popen (String_Type cmd, String_Type mode)
+
+ DESCRIPTION
+ The `popen' function executes a process specified by `cmd'
+ and opens a unidirectional pipe to the newly created process. The
+ `mode' indicates whether or not the pipe is open for reading
+ or writing. Specifically, if `mode' is `"r"', then the
+ pipe is opened for reading, or if `mode' is `"w"', then the
+ pipe will be open for writing.
+
+ Upon success, a `File_Type' pointer will be returned, otherwise
+ the function failed and `NULL' will be returned.
+
+ NOTES
+ This function is not available on all systems.
+
+ SEE ALSO
+ pclose, fopen
+--------------------------------------------------------------
+
+printf
+
+ SYNOPSIS
+ Create and write a formatted string to stdout
+
+ USAGE
+ Int_Type printf (String_Type fmt, ...)
+
+ DESCRIPTION
+ `fprintf' formats the objects specified by the variable argument
+ list according to the format `fmt' and write the result to
+ `stdout'. This function is equivalent to `fprintf' used
+ with the `stdout' file pointer. See `fprintf' for more
+ information.
+
+ `printf' returns the number of characters written to the file,
+ or -1 upon error.
+
+ NOTES
+ Many C programmers do not check the return status of the
+ `printf' C library function. Make sure that if you do not care
+ about whether or not the function succeeds, then code it as in the
+ following example:
+
+ () = printf ("%s laid %d eggs\n", chicken_name, num_egg);
+
+
+ SEE ALSO
+ fputs, printf, fwrite, message
+--------------------------------------------------------------
+
+Sprintf
+
+ SYNOPSIS
+ Format objects into a string
+
+ USAGE
+ String_Type Sprintf (String_Type format, ..., Integer_Type n)
+
+ DESCRIPTION
+ `Sprintf' formats a string from `n' objects according to
+ `format'. Unlike `sprintf', the `Sprintf' function
+ requires the number of items to format.
+
+ The format string is a C library `sprintf' style format
+ descriptor. Briefly, the format string may consist of ordinary
+ characters (not including the `%' character), which are copied
+ into the output string as-is, and a conversion specification
+ introduced by the `%' character. The `%' character must be
+ followed by at least one other character to specify the conversion:
+
+ s value is a string
+ f value is a floating point number
+ e print float in exponential form, e.g., 2.345e08
+ g print float as e or g, depending upon its value
+ c value is an ascii character
+ % print the percent character
+ d print a signed decimal integer
+ u print an unsigned decimal integer
+ o print an integer as octal
+ X print an integer as hexadecimal
+ S convert value to a string and format as string
+
+ Note that `%S' is a S-Lang extension which will cause the value
+ to be formatted as string. In fact, `sprintf("%S",x)' is
+ equivalent to `sprintf("%s",string(x))'.
+
+ s = Sprintf("%f is greater than %f but %s is better than %s\n",
+ PI, E, "Cake" "Pie", 4);
+
+ The final argument to `Sprintf' is the number of items to format; in
+ this case, there are 4 items.
+
+ SEE ALSO
+ sprintf, string, sscanf
+--------------------------------------------------------------
+
+create_delimited_string
+
+ SYNOPSIS
+ Concatenate strings using a delimiter
+
+ USAGE
+ String_Type create_delimited_string (delim, s_1, s_2, ..., s_n, n)
+
+ String_Type delim, s_1, ..., s_n
+ Integer_Type n
+
+
+ DESCRIPTION
+ `create_delimited_string' performs a concatenation operation on
+ the `n' strings `s_1', ...,`s_n', using the string
+ `delim' as a delimiter. The resulting string is equivalent to
+ one obtained via
+
+ s_1 + delim + s_2 + delim + ... + s_n
+
+
+ EXAMPLE
+ One use for this function is to construct path names, e.g.,
+
+ create_delimited_string ("/", "user", "local", "bin", 3);
+
+ will produce `"usr/local/bin"'.
+
+ NOTES
+ The expression `strcat(a,b)' is equivalent to
+ `create_delimited_string("", a, b, 2)'.
+
+ SEE ALSO
+ strjoin, is_list_element, extract_element, strchop, strcat
+--------------------------------------------------------------
+
+extract_element
+
+ SYNOPSIS
+ Extract the nth element of a string with delimiters
+
+ USAGE
+ String_Type extract_element (String_Type list, Integer_Type nth, Integer_Type delim);
+
+ DESCRIPTION
+ The `extract_element' function may be used to extract the
+ `nth' element of the `delim' delimited list of strings
+ `list'. The function will return the `nth' element of the
+ list, unless `nth' specifies more elements than the list
+ contains, in which case `NULL' will be returned.
+ Elements in the list are numbered from `0'.
+
+ EXAMPLE
+ The expression
+
+ extract_element ("element 0, element 1, element 2", 1, ',')
+
+ returns the string `" element 1"', whereas
+
+ extract_element ("element 0, element 1, element 2", 1, ' ')
+
+ returns `"0,"'.
+
+ The following function may be used to compute the number of elements
+ in the list:
+
+ define num_elements (list, delim)
+ {
+ variable nth = 0;
+ while (NULL != extract_element (list, nth, delim))
+ nth++;
+ return nth;
+ }
+
+
+ Alternatively, the `strchop' function may be more useful. In
+ fact, `extract_element' may be expressed in terms of the
+ function `strchop' as
+
+ define extract_element (list, nth, delim)
+ {
+ list = strchop(list, delim, 0);
+ if (nth >= length (list))
+ return NULL;
+ else
+ return list[nth];
+ }
+
+ and the `num_elements' function used above may be recoded more
+ simply as:
+
+ define num_elements (list, delim)
+ {
+ return length (strchop (length, delim, 0));
+ }
+
+
+ SEE ALSO
+ is_list_element, is_substr, strtok, strchop, create_delimited_string
+--------------------------------------------------------------
+
+is_list_element
+
+ SYNOPSIS
+ Test whether a delimited string contains a specific element
+
+ USAGE
+ Integer_Type is_list_element (String_Type list, String_Type elem, Integer_Type delim)
+
+ DESCRIPTION
+ The `is_list_element' function may be used to determine whether
+ or not a delimited list of strings, `list', contains the element
+ `elem'. If `elem' is not an element of `list', the function
+ will return zero, otherwise, it returns 1 plus the matching element
+ number.
+
+ EXAMPLE
+ The expression
+
+ is_list_element ("element 0, element 1, element 2", "0,", ' ');
+
+ returns `2' since `"0,"' is element number one of the list
+ (numbered from zero).
+
+ SEE ALSO
+ extract_element, is_substr, create_delimited_string
+--------------------------------------------------------------
+
+is_substr
+
+ SYNOPSIS
+ Test for a specified substring within a string.
+
+ USAGE
+ Integer_Type is_substr (String_Type a, String_Type b)
+
+ DESCRIPTION
+ This function may be used to determine if `a' contains the
+ string `b'. If it does not, the function returns 0; otherwise it
+ returns the position of the first occurance of `b' in `a'.
+
+ NOTES
+ It is important to remember that the first character of a string
+ corresponds to a position value of `1'.
+
+ SEE ALSO
+ substr, string_match, strreplace
+--------------------------------------------------------------
+
+make_printable_string
+
+ SYNOPSIS
+ Format a string suitable for parsing
+
+ USAGE
+ String_Type make_printable_string(String_Type str)
+
+ DESCRIPTION
+ This function formats a string in such a way that it may be used as
+ an argument to the `eval' function. The resulting string is
+ identical to `str' except that it is enclosed in double quotes and the
+ backslash, newline, and double quote characters are expanded.
+
+ SEE ALSO
+ eval, str_quote_string
+--------------------------------------------------------------
+
+sprintf
+
+ SYNOPSIS
+ Format objects into a string
+
+ USAGE
+ String sprintf (String format, ...);
+
+ DESCRIPTION
+ This function performs a similar task as the C function with the same
+ name. It differs from the S-Lang function `Sprintf' in that it
+ does not require the number of items to format.
+ See the documentation for `Sprintf' for more information.
+
+ SEE ALSO
+ Sprintf, string, sscanf, vmessage
+--------------------------------------------------------------
+
+sscanf
+
+ SYNOPSIS
+ Parse a formatted string
+
+ USAGE
+ Int_Type sscanf (s, fmt, r1, ... rN)
+
+ String_Type s, fmt;
+ Ref_Type r1, ..., rN
+
+
+ DESCRIPTION
+ The `sscanf' function parses the string `s' according to the
+ format `fmt' and sets the variables whose references are given by
+ `r1', ..., `rN'. The function returns the number of
+ references assigned, or `-1' upon error.
+
+ The format string `fmt' consists of ordinary characters and
+ conversion specifiers. A conversion specifier begins with the
+ special character `%' and is described more fully below. A white
+ space character in the format string matches any amount of whitespace
+ in the input string. Parsing of the format string stops whenever a
+ match fails.
+
+ The `%' is used to denote a conversion specifier whose general
+ form is given by `%[*][width][type]format' where the brackets
+ indicate optional items. If `*' is present, then the conversion
+ will be performed by no assignment to a reference will be made. The
+ `width' specifier specifies the maximum field width to use for
+ the conversion. The `type' modifier is used to indicate size of
+ the object, e.g., a short integer, as follows.
+
+ If _type_ is given as the character `h', then if the format
+ conversion is for an integer (`dioux'), the object assigned will
+ be a short integer. If _type_ is `l', then the conversion
+ will be to a long integer for integer conversions, or to a double
+ precession floating point number for floating point conversions.
+
+ The format specifier is a character that specifies the conversion:
+
+ % Matches a literal percent character. No assigment is
+ performed.
+ d Matches a signed decimal integer.
+ D Matches a long decimal integer (equiv to `ld')
+ u Matches an unsigned decimal integer
+ U Matches an unsigned long decimal integer (equiv to `lu')
+ i Matches either a hexidecimal integer, decimal integer, or
+ octal integer.
+ I Equivalent to `li'.
+ x Matches a hexidecimal integer.
+ X Matches a long hexidecimal integer (same as `lx').
+ e,f,g Matches a decimal floating point number (Float_Type).
+ E,F,G Matches a double precision floating point number, same as `lf'.
+ s Matches a string of non-whitespace characters (String_Type).
+ c Matches one character. If width is given, width
+ characters are matched.
+ n Assigns the number of characters scanned so far.
+ [...] Matches zero or more characters from the set of characters
+ enclosed by the square brackets. If '^' is given as the
+ first character, then the complement set is matched.
+
+
+ EXAMPLE
+ Suppose that `s' is `"Coffee: (3,4,12.4)"'. Then
+
+ n = sscanf (s, "%[a-zA-Z]: (%d,%d,%lf)", &item, &x, &y, &z);
+
+ will set `n' to 4, `item' to `"Coffee"', `x' to 3,
+ `y' to 4, and `z' to the double precision number
+ `12.4'. However,
+
+ n = sscanf (s, "%s: (%d,%d,%lf)", &item, &x, &y, &z);
+
+ will set `n' to 1, `item' to `"Coffee:"' and the
+ remaining variables will not be assigned.
+
+ SEE ALSO
+ sprintf, unpack, string, atof, int, integer, string_match
+--------------------------------------------------------------
+
+str_delete_chars
+
+ SYNOPSIS
+ Delete characters from a string
+
+ USAGE
+ String_Type str_delete_chars (String_Type str, String_Type del_set
+
+ DESCRIPTION
+ This function may be used to delete the set of characters specified
+ by `del_set' from the string `str'. The result is returned.
+
+ EXAMPLE
+
+ str = str_delete_chars (str, "^A-Za-z");
+
+ will remove all characters except `A-Z' and `a-z' from
+ `str'.
+--------------------------------------------------------------
+
+str_quote_string
+
+ SYNOPSIS
+ Escape characters in a string.
+
+ USAGE
+ String_Type str_quote_string(String_Type str, String_Type qlis, Integer_Type quote)
+
+ DESCRIPTION
+ The `str_quote_string' returns a string identical to `str'
+ except that all characters in the set specified by the string
+ `qlis' are escaped with the `quote' character, including the
+ quote character itself. This function is useful for making a
+ string that can be used in a regular expression.
+
+ EXAMPLE
+ Execution of the statements
+
+ node = "Is it [the coat] really worth $100?";
+ tag = str_quote_string (node, "\\^$[]*.+?", '\\');
+
+ will result in `tag' having the value:
+
+ Is it \[the coat\] really worth \$100\?
+
+
+ SEE ALSO
+ str_uncomment_string, make_printable_string
+--------------------------------------------------------------
+
+str_replace
+
+ SYNOPSIS
+ Replace a substring of a string
+
+ USAGE
+ Integer_Type str_replace (String_Type a, String_Type b, String_Type c)
+
+ DESCRIPTION
+ The `str_replace' function replaces the first occurance of `b' in
+ `a' with `c' and returns an integer that indicates whether a
+ replacement was made or not. If `b' does not occur in `a', zero is
+ returned. However, if `b' occurs in `a', a non-zero integer is
+ returned as well as the new string resulting from the replacement.
+
+ NOTES
+ This function has been superceded by `strreplace'.
+
+ SEE ALSO
+ strreplace
+--------------------------------------------------------------
+
+str_uncomment_string
+
+ SYNOPSIS
+ Remove comments from a string
+
+ USAGE
+ String_Type str_uncomment_string(String_Type s, String_Type beg, String_Type end)
+
+ DESCRIPTION
+ This function may be used to remove comments from a string `s'.
+ The parameters, `beg' and `end', are strings of equal length
+ whose corresponding characters specify the begin and end comment
+ characters, respectively. It returns the uncommented string.
+
+ EXAMPLE
+ The expression
+
+ str_uncomment_string ("Hello (testing) 'example' World", "'(", "')")
+
+ returns the string `"Hello World"'.
+
+ NOTES
+ This routine does not handle multicharacter comment delimiters and it
+ assumes that comments are not nested.
+
+ SEE ALSO
+ str_quote_string
+--------------------------------------------------------------
+
+strcat
+
+ SYNOPSIS
+ Concatenate strings
+
+ USAGE
+ String_Type strcat (String_Type a_1, ..., String_Type a_N)
+
+ DESCRIPTION
+ The `strcat' function concatenates its N `String_Type'
+ arguments `a_1', ... `a_N' together and returns the result.
+
+ EXAMPLE
+
+ strcat ("Hello", " ", "World");
+
+ produces the string `"Hello World"'.
+
+ NOTES
+ This function is equivalent to the binary operation `a_1+...+a_N'.
+ However, `strcat' is much faster making it the preferred method
+ to concatenate string.
+
+ SEE ALSO
+ sprintf, create_delimited_string
+--------------------------------------------------------------
+
+strchop
+
+ SYNOPSIS
+ Chop or split a string into substrings.
+
+ USAGE
+ String_Type[] strchop (String_Type str, Integer_Type delim, Integer_Type quote)
+
+ DESCRIPTION
+ The `strchop' function may be used to split-up a string
+ `str' that consists of substrings delimited by the character
+ specified by `delim'. If the integer `quote' is non-zero,
+ it will be taken as a quote character for the delimiter. The
+ function returns the substrings as an array.
+
+ EXAMPLE
+ The following function illustrates how to sort a comma separated
+ list of strings:
+
+ define sort_string_list (a)
+ {
+ variable i, b, c;
+ b = strchop (a, ',', 0);
+
+ i = array_sort (b, &strcmp);
+ b = b[i]; % rearrange
+
+ % Convert array back into comma separated form
+ return strjoin (b, ",");
+ }
+
+
+ NOTES
+ The semantics of this `strchop' and `strchopr' have been
+ changed since version 1.2.x of the interpreter. Old versions of
+ these functions returned the values on the stack, which meant that
+ one could not chop up arbitrarily long strings that consist of
+ many substrings.
+
+ The function `strchopr' should be used if it is desired to have
+ the string chopped-up in the reverse order.
+
+ SEE ALSO
+ strchopr, extract_element, strjoin, strtok
+--------------------------------------------------------------
+
+strchopr
+
+ SYNOPSIS
+ Chop or split a string into substrings.
+
+ USAGE
+ String_Type[] strchopr (String_Type str, String_Type delim, String_Type quote)
+
+ DESCRIPTION
+ This routine performs exactly the same function as `strchop' except
+ that it returns the substrings in the reverse order. See the
+ documentation for `strchop' for more information.
+
+ SEE ALSO
+ strchop, extract_element, strtok, strjoin
+--------------------------------------------------------------
+
+strcmp
+
+ SYNOPSIS
+ Compare two strings
+
+ USAGE
+ Interpret strcmp (String_Type a, String_Type b)
+
+ DESCRIPTION
+ The `strcmp' function may be used to perform a case-sensitive
+ string comparison, in the lexicongraphic sense, on strings `a' and
+ `b'. It returns 0 if the strings are identical, a negative integer
+ if `a' is less than `b', or a positive integer if `a' is greater
+ than `b'.
+
+ EXAMPLE
+ The `strup' function may be used to perform a case-insensitive
+ string comparison:
+
+ define case_insensitive_strcmp (a, b)
+ {
+ return strcmp (strup(a), strup(b));
+ }
+
+
+ NOTES
+ One may also use one of the binary comparison operators, e.g.,
+ `a > b'.
+
+ SEE ALSO
+ strup, strncmp
+--------------------------------------------------------------
+
+strcompress
+
+ SYNOPSIS
+ Remove excess whitespace characters from a string
+
+ USAGE
+ String_Type strcompress (String_Type s, String_Type white)
+
+ DESCRIPTION
+ The `strcompress' function compresses the string `s' by
+ replacing a sequence of one or more characters from the set
+ `white' by the first character of `white'. In addition, it
+ also removes all leading and trailing characters from `s' that
+ are part of `white'.
+
+ EXAMPLE
+ The expression
+
+ strcompress (",;apple,,cherry;,banana", ",;");
+
+ returns the string `"apple,cherry,banana"'.
+
+ SEE ALSO
+ strtrim, strtrans
+--------------------------------------------------------------
+
+string_match
+
+ SYNOPSIS
+ Match a string against a regular expression
+
+ USAGE
+ Integer_Type string_match(String_Type str, String_Type pat, Integer_Type pos)
+
+ DESCRIPTION
+ The `string_match' function returns zero if `str' does not
+ match regular expression specified by `pat'. This function
+ performs the match starting at position `pos' (numbered from 1) in
+ `str'. This function returns the position of the start of the
+ match. To find the exact substring actually matched, use
+ `string_match_nth'.
+
+ SEE ALSO
+ string_match_nth, strcmp, strncmp
+--------------------------------------------------------------
+
+string_match_nth
+
+ SYNOPSIS
+ Get the result of the last call to string_match
+
+ USAGE
+ (Integer_Type, Integer_Type) = string_match_nth(Integer_Type nth)
+
+ DESCRIPTION
+ The `string_match_nth' function returns two integers describing
+ the result of the last call to `string_match'. It returns both
+ the offset into the string and the length of characters matches by
+ the `nth' submatch.
+
+ By convention, `nth' equal to zero means the entire match.
+ Otherwise, `nth' must be an integer with a value 1 through 9,
+ and refers to the set of characters matched by the `nth' regular
+ expression enclosed by the pairs `\(, \)'.
+
+ EXAMPLE
+ Consider:
+
+ variable matched, pos, len;
+ matched = string_match("hello world", "\\([a-z]+\\) \\([a-z]+\\)", 1);
+ if (matched) (pos, len) = string_match_nth(2);
+
+ This will set `matched' to 1 since a match will be found at the
+ first position, `pos' to 6 since `w' is offset 6 characters
+ from the beginning of the string, and `len' to 5 since
+ `"world"' is 5 characters long.
+
+ NOTES
+ The position offset is _not_ affected by the value of the offset
+ parameter to the `string_match' function. For example, if the
+ value of the last parameter to the `string_match' function had
+ been 3, `pos' would still have been set to 6.
+
+ Note also that `string_match_nth' returns the _offset_ from
+ the beginning of the string and not the position of the match.
+
+ SEE ALSO
+ string_match
+--------------------------------------------------------------
+
+strjoin
+
+ SYNOPSIS
+ Concatenate elements of a string array
+
+ USAGE
+ String_Type strjoin (Array_Type a, String_Type delim)
+
+ DESCRIPTION
+ The `strjoin' function operates on an array of strings by joining
+ successive elements together separated with a delimiter `delim'.
+ If `delim' is the empty string `""', then the result will
+ simply be the concatenation of the elements.
+
+ EXAMPLE
+ Suppose that
+
+ days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
+
+ Then `strjoin (days,"+")' will produce
+ `"Sun+Mon+Tue+Wed+Thu+Fri+Sat+Sun"'. Similarly,
+ `strjoin (["","",""], "X")' will produce `"XX"'.
+
+ SEE ALSO
+ create_delimited_string, strchop, strcat
+--------------------------------------------------------------
+
+strlen
+
+ SYNOPSIS
+ Compute the length of a string
+
+ USAGE
+ Integer_Type strlen (String_Type a)
+
+ DESCRIPTION
+ The `strlen' function may be used to compute the length of a string.
+
+ EXAMPLE
+ After execution of
+
+ variable len = strlen ("hello");
+
+ `len' will have a value of `5'.
+
+ SEE ALSO
+ bstrlen, length, substr
+--------------------------------------------------------------
+
+strlow
+
+ SYNOPSIS
+ Convert a string to lowercase
+
+ USAGE
+ String_Type strlow (String_Type s)
+
+ DESCRIPTION
+ The `strlow' function takes a string `s' and returns another
+ string identical to `s' except that all upper case characters
+ that comprise `s' will be converted to lower case.
+
+ EXAMPLE
+ The function
+
+ define Strcmp (a, b)
+ {
+ return strcmp (strlow (a), strlow (b));
+ }
+
+ performs a case-insensitive comparison operation of two strings by
+ converting them to lower case first.
+
+ SEE ALSO
+ strup, tolower, strcmp, strtrim, define_case
+--------------------------------------------------------------
+
+strncmp
+
+ SYNOPSIS
+ Compare the first few characters of two strings
+
+ USAGE
+ Integer_Type strncmp (String_Type a, String_Type b, Integer_Type n)
+
+ DESCRIPTION
+ This function behaves like `strcmp' except that it compares only the
+ first `n' characters in the strings `a' and `b'. See
+ the documentation for `strcmp' for information about the return
+ value.
+
+ EXAMPLE
+ The expression
+
+ strcmp ("apple", "appliance", 3);
+
+ will return zero since the first three characters match.
+
+ SEE ALSO
+ strcmp, strlen
+--------------------------------------------------------------
+
+strreplace
+
+ SYNOPSIS
+ Replace one or more substrings
+
+ USAGE
+ (new, n) = strreplace (a, b, c, max_n)
+
+ String_Type a, b, c, rep;
+ Int_Type n, max_n;
+
+
+ DESCRIPTION
+ The `strreplace' function may be used to replace one or more
+ occurances of `b' in `a' with `c'. If the integer
+ `max_n' is positive, then the first `max_n' occurances of
+ `b' in `a' will be replaced. Otherwise, if `max_n' is
+ negative, then the last `abs(max_n)' occurances will be replaced.
+
+ The function returns the resulting string and an integer indicating
+ how many replacements were made.
+
+ EXAMPLE
+ The following function illustrates how `strreplace' may be used
+ to remove all occurances of a specified substring
+
+ define delete_substrings (a, b)
+ {
+ (a, ) = strreplace (a, b, "", strlen (a));
+ return a;
+ }
+
+
+ SEE ALSO
+ is_substr, strsub, strtrim, strtrans, str_delete_chars
+--------------------------------------------------------------
+
+strsub
+
+ SYNOPSIS
+ Replace a character with another in a string.
+
+ USAGE
+ String_Type strsub (String_Type s, Integer_Type pos, Integer_Type ch)
+
+ DESCRIPTION
+ The `strsub' character may be used to substitute the character
+ `ch' for the character at position `pos' of the string
+ `s'. The resulting string is returned.
+
+ EXAMPLE
+
+ define replace_spaces_with_comma (s)
+ {
+ variable n;
+ while (n = is_substr (s, " "), n) s = strsub (s, n, ',');
+ return s;
+ }
+
+ For uses such as this, the `strtrans' function is a better choice.
+
+ NOTES
+ The first character in the string `s' is specified by `pos'
+ equal to 1.
+
+ SEE ALSO
+ is_substr, strreplace, strlen
+--------------------------------------------------------------
+
+strtok
+
+ SYNOPSIS
+ Extract tokens from a string
+
+ USAGE
+ String_Type[] strtok (String_Type str [,String_Type white])
+
+ DESCRIPTION
+ `strtok' breaks the string `str' into a series of tokens and
+ returns them as an array of strings. If the second parameter
+ `white' is present, then it specifies the set of characters that
+ are to be regarded as whitespace when extracting the tokens, and may
+ consist of the whitespace characters or a range of such characters.
+ If the first character of `white' is `'^'', then the
+ whitespace characters consist of all characters except those in
+ `white'. For example, if `white' is `" \t\n,;."',
+ then those characters specifiy the whitespace characters. However,
+ if `white' is given by `"^a-zA-Z0-9_"', then any character
+ is a whitespace character except those in the ranges `a-z',
+ `A-Z', `0-9', and the underscore character.
+
+ If the second parameter is not present, then it defaults to
+ `" \t\r\n\f"'.
+
+ EXAMPLE
+ The following example may be used to count the words in a text file:
+
+ define count_words (file)
+ {
+ variable fp, line, count;
+
+ fp = fopen (file, "r");
+ if (fp == NULL) return -1;
+
+ count = 0;
+ while (-1 != fgets (&line, fp))
+ {
+ line = strtok (line, "^a-zA-Z");
+ count += length (line);
+ }
+ () = fclose (fp);
+ return count;
+ }
+
+
+ SEE ALSO
+ strchop, strcompress, extract_element, strjoin
+--------------------------------------------------------------
+
+strtrans
+
+ SYNOPSIS
+ Replace characters in a string
+
+ USAGE
+ String_Type strtrans (str, old_set, new_set)
+
+ String_Type str, old_set, new_set;
+
+
+ DESCRIPTION
+ The `strtrans' function may be used to replace all the characters
+ from the set `old_set' with the corresponding characters from
+ `new_set' in the string `str'. If `new_set' is empty,
+ then the characters in `old_set' will be removed from `str'.
+ This function returns the result.
+
+ EXAMPLE
+
+ str = strtrans (str, "A-Z", "a-z"); % lower-case str
+ str = strtrans (str, "^0-9", " "); % Replace anything but 0-9 by space
+
+
+ SEE ALSO
+ strreplace, strtrim, strup, strlow
+--------------------------------------------------------------
+
+strtrim
+
+ SYNOPSIS
+ Remove whitespace from the ends of a string
+
+ USAGE
+ String_Type strtrim (String_Type s [,String_Type w])
+
+ DESCRIPTION
+ The `strtrim' function removes all leading and trailing whitespace
+ characters from the string `s' and returns the result. The
+ optional second parameter specifies the set of whitespace
+ characters. If the argument is not present, then the set defaults
+ to `" \t\r\n"'.
+
+ SEE ALSO
+ strtrim_beg, strtrim_end, strcompress
+--------------------------------------------------------------
+
+strtrim_beg
+
+ SYNOPSIS
+ Remove leading whitespace from a string
+
+ USAGE
+ String_Type strtrim_beg (String_Type s [,String_Type w])
+
+ DESCRIPTION
+ The `strtrim_beg' function removes all leading whitespace
+ characters from the string `s' and returns the result. The
+ optional second parameter specifies the set of whitespace
+ characters. If the argument is not present, then the set defaults
+ to `" \t\r\n"'.
+
+ SEE ALSO
+ strtrim, strtrim_end, strcompress
+--------------------------------------------------------------
+
+strtrim_end
+
+ SYNOPSIS
+ Remove trailing whitespace from a string
+
+ USAGE
+ String_Type strtrim_end (String_Type s [,String_Type w])
+
+ DESCRIPTION
+ The `strtrim_end' function removes all trailing whitespace
+ characters from the string `s' and returns the result. The
+ optional second parameter specifies the set of whitespace
+ characters. If the argument is not present, then the set defaults
+ to `" \t\r\n"'.
+
+ SEE ALSO
+ strtrim, strtrim_beg, strcompress
+--------------------------------------------------------------
+
+strup
+
+ SYNOPSIS
+ Convert a string to uppercase
+
+ USAGE
+ String_Type strup (String_Type s)
+
+ DESCRIPTION
+ The `strup' function takes a string `s' and returns another
+ string identical to `s' except that all lower case characters
+ that comprise `s' will be converted to upper case.
+
+ EXAMPLE
+ The function
+
+ define Strcmp (a, b)
+ {
+ return strcmp (strup (a), strup (b));
+ }
+
+ performs a case-insensitive comparison operation of two strings by
+ converting them to upper case first.
+
+ SEE ALSO
+ strlow, toupper, strcmp, strtrim, define_case, strtrans
+--------------------------------------------------------------
+
+substr
+
+ SYNOPSIS
+ Extract a substring from a string
+
+ USAGE
+ String_Type substr (String_Type s, Integer_Type n, Integer_Type len)
+
+ DESCRIPTION
+ The `substr' function returns a substring with length `len'
+ of the string `s' beginning at position `n'. If `len' is
+ `-1', the entire length of the string `s' will be used for
+ `len'. The first character of `s' is given by `n' equal
+ to 1.
+
+ EXAMPLE
+
+ substr ("To be or not to be", 7, 5);
+
+ returns `"or no"'
+
+ NOTES
+ In many cases it is more convenient to use array indexing rather
+ than the `substr' function. In fact, `substr(s,i+1,strlen(s))' is
+ equivalent to `s[[i:]]'.
+
+ SEE ALSO
+ is_substr, strlen
+--------------------------------------------------------------
+
+_push_struct_field_values
+
+ SYNOPSIS
+ Push the values of a structure's fields onto the stack
+
+ USAGE
+ Integer_Type num = _push_struct_field_values (Struct_Type s)
+
+ DESCRIPTION
+ The `_push_struct_field_values' function pushes the values of
+ all the fields of a structure onto the stack, returning the
+ number of items pushed. The fields are pushed such that the last
+ field of the structure is pushed first.
+
+ SEE ALSO
+ get_struct_field_names, get_struct_field
+--------------------------------------------------------------
+
+get_struct_field
+
+ SYNOPSIS
+ Get the value associated with a structure field
+
+ USAGE
+ x = get_struct_field (Struct_Type s, String field_name)
+
+ DESCRIPTION
+ The `get_struct_field' function gets the value of the field
+ whose name is specified by `field_name' of the structure `s'.
+
+ EXAMPLE
+ The following example illustrates how this function may be used to
+ to print the value of a structure.
+
+ define print_struct (s)
+ {
+ variable name;
+
+ foreach (get_struct_field_names (s))
+ {
+ name = ();
+ value = get_struct_field (s, name);
+ vmessage ("s.%s = %s\n", name, string(value));
+ }
+ }
+
+
+ SEE ALSO
+ set_struct_field, get_struct_field_names, array_info
+--------------------------------------------------------------
+
+get_struct_field_names
+
+ SYNOPSIS
+ Retrieve the field names associated with a structure
+
+ USAGE
+ String_Type[] = get_struct_field_names (Struct_Type s)
+
+ DESCRIPTION
+ The `get_struct_field_names' function returns an array of
+ strings whose elements specify the names of the fields of the
+ struct `s'.
+
+ EXAMPLE
+ The following example illustrates how the
+ `get_struct_field_names' function may be used to print the
+ value of a structure.
+
+ define print_struct (s)
+ {
+ variable name, value;
+
+ foreach (get_struct_field_names (s))
+ {
+ name = ();
+ value = get_struct_field (s, name);
+ vmessage ("s.%s = %s\n", name, string (value));
+ }
+ }
+
+
+ SEE ALSO
+ _push_struct_field_values, get_struct_field
+--------------------------------------------------------------
+
+is_struct_type
+
+ SYNOPSIS
+ Determine whether or not an object is a structure
+
+ USAGE
+ Integer_Type is_struct_type (X)
+
+ DESCRIPTION
+ The `is_struct_type' function returns 1 if the parameter
+ refers to a structure or a user-defined type. If the object is
+ neither, 0 will be returned.
+
+ SEE ALSO
+ typeof, _typeof
+--------------------------------------------------------------
+
+set_struct_field
+
+ SYNOPSIS
+ Set the value associated with a structure field
+
+ USAGE
+ set_struct_field (s, field_name, field_value)
+
+ Struct_Type s;
+ String_Type field_name;
+ Generic_Type field_value;
+
+
+ DESCRIPTION
+ The `set_struct_field' function sets the value of the field
+ whose name is specified by `field_name' of the structure
+ `s' to `field_value'.
+
+ SEE ALSO
+ get_struct_field, get_struct_field_names, set_struct_fields, array_info
+--------------------------------------------------------------
+
+set_struct_fields
+
+ SYNOPSIS
+ Set the fields of a structure
+
+ USAGE
+ set_struct_fields (Struct_Type s, ...)
+
+ DESCRIPTION
+ The `set_struct_fields' function may be used to set zero or more
+ fields of a structure. The fields are set in the order in which
+ they were created when the structure was defined.
+
+ EXAMPLE
+
+ variable s = struct { name, age, height };
+ set_struct_fields (s, "Bill", 13, 64);
+
+
+ SEE ALSO
+ set_struct_field, get_struct_field_names
+--------------------------------------------------------------
+
+_time
+
+ SYNOPSIS
+ Get the current time in seconds
+
+ USAGE
+ ULong_Type _time ()
+
+ DESCRIPTION
+ The `_time' function returns the number of elapsed seconds since
+ 00:00:00 GMT, January 1, 1970. The `ctime' function may be used
+ to convert this into a string representation.
+
+ SEE ALSO
+ ctime, time, localtime, gmtime
+--------------------------------------------------------------
+
+ctime
+
+ SYNOPSIS
+ Convert a calendar time to a string
+
+ USAGE
+ String_Type ctime(ULong_Type secs)
+
+ DESCRIPTION
+ This function returns a string representation of the time as given
+ by `secs' seconds since 1970.
+
+ SEE ALSO
+ time, _time, localtime, gmtime
+--------------------------------------------------------------
+
+gmtime
+
+ SYNOPSIS
+ Break down a time in seconds to GMT timezone
+
+ USAGE
+ Struct_Type gmtime (Long_Type secs)
+
+ DESCRIPTION
+ The `gmtime' function is exactly like `localtime' except
+ that the values in the structure it returns are with respect to GMT
+ instead of the local timezone. See the documentation for
+ `localtime' for more information.
+
+ NOTES
+ On systems that do not support the `gmtime' C library function,
+ this function is the same as `localtime'.
+
+ SEE ALSO
+ localtime, _time
+--------------------------------------------------------------
+
+localtime
+
+ SYNOPSIS
+ Break down a time in seconds to local timezone
+
+ USAGE
+ Struct_Type localtime (Long_Type secs)
+
+ DESCRIPTION
+ The `localtime' function takes a parameter `secs'
+ representing the number of seconds since 00:00:00, January 1 1970
+ UTC and returns a structure containing information about `secs'
+ in the local timezone. The structure contains the following
+ `Int_Type' fields:
+
+ `tm_sec' The number of seconds after the minute, normally
+ in the range 0 to 59, but can be up to 61 to allow for
+ leap seconds.
+
+ `tm_min' The number of minutes after the hour, in the
+ range 0 to 59.
+
+ `tm_hour' The number of hours past midnight, in the range
+ 0 to 23.
+
+ `tm_mday' The day of the month, in the range 1 to 31.
+
+ `tm_mon' The number of months since January, in the range
+ 0 to 11.
+
+ `tm_year' The number of years since 1900.
+
+ `tm_wday' The number of days since Sunday, in the range 0
+ to 6.
+
+ `tm_yday' The number of days since January 1, in the
+ range 0 to 365.
+
+ `tm_isdst' A flag that indicates whether daylight saving
+ time is in effect at the time described. The value is
+ positive if daylight saving time is in effect, zero if it
+ is not, and negative if the information is not available.
+
+ SEE ALSO
+ gmtime, _time, ctime
+--------------------------------------------------------------
+
+tic
+
+ SYNOPSIS
+ Start timing
+
+ USAGE
+ void tic ()
+
+ DESCRIPTION
+ The `tic' function restarts the internal clock used for timing
+ the execution of commands. To get the elapsed time of the clock,
+ use the `toc' function.
+
+ SEE ALSO
+ toc, times
+--------------------------------------------------------------
+
+time
+
+ SYNOPSIS
+ Return the current data and time as a string
+
+ USAGE
+ String_Type time ()
+
+ DESCRIPTION
+ This function returns the current time as a string of the form:
+
+ Sun Apr 21 13:34:17 1996
+
+
+ SEE ALSO
+ ctime, message, substr
+--------------------------------------------------------------
+
+times
+
+ SYNOPSIS
+ Get process times
+
+ USAGE
+ Struct_Type times ()
+
+ DESCRIPTION
+ The `times' function returns a structure containing the
+ following fields:
+
+ tms_utime (user time)
+ tms_stime (system time)
+ tms_cutime (user time of child processes)
+ tms_cstime (system time of child processes)
+
+
+ NOTES
+ Not all systems support this function.
+
+ SEE ALSO
+ tic, toc, _times
+--------------------------------------------------------------
+
+toc
+
+ SYNOPSIS
+ Get elapsed CPU time
+
+ USAGE
+ Double_Type toc ()
+
+ DESCRIPTION
+ The `toc' function returns the elapsed CPU time in seconds since
+ the last call to `tic'. The CPU time is the amount of time the
+ CPU spent running the code of the current process.
+
+ EXAMPLE
+ The `tic' and `toc' functions are ideal for timing the
+ execution of the interpreter:
+
+ variable a = "hello", b = "world", c, n = 100000, t;
+
+ tic (); loop (n) c = a + b; t = toc ();
+ vmessage ("a+b took %f seconds\n", t);
+ tic (); loop (n) c = strcat(a,b); t = toc ();
+ vmessage ("strcat took %f seconds\n", t);
+
+
+ NOTES
+ This function may not be available on all systems.
+
+ The implementation of this function is based upon the `times'
+ system call. The precision of the clock is system dependent.
+
+ SEE ALSO
+ tic, times, _time
+--------------------------------------------------------------
+
+_slang_guess_type
+
+ SYNOPSIS
+ Guess the data type that a string represents.
+
+ USAGE
+ DataType_Type _slang_guess_type (String_Type s)
+
+ DESCRIPTION
+ This function tries to determine whether its argument `s'
+ represents an integer (short, int, long), floating point (float,
+ double), or a complex number. If it appears to be none of these,
+ then a string is assumed. It returns one of the following values
+ depending on the format of the string `s':
+
+ Short_Type : short integer (e.g., "2h")
+ UShort_Type : unsigned short integer (e.g., "2hu")
+ Integer_Type : integer (e.g., "2")
+ UInteger_Type : unsigned integer (e.g., "2")
+ Long_Type : long integer (e.g., "2l")
+ ULong_Type : unsigned long integer (e.g., "2l")
+ Float_Type : float (e.g., "2.0f")
+ Double_Type : double (e.g., "2.0")
+ Complex_Type : imaginary (e.g., "2i")
+ String_Type : Anything else. (e.g., "2foo")
+
+ For example, `_slang_guess_type("1e2")' returns
+ `Double_Type' but `_slang_guess_type("e12")' returns
+ `String_Type'.
+
+ SEE ALSO
+ integer, string, double, atof
+--------------------------------------------------------------
+
+_typeof
+
+ SYNOPSIS
+ Get the data type of an object
+
+ USAGE
+ DataType_Type _typeof (x)
+
+ DESCRIPTION
+ This function is similar to the `typeof' function except in the
+ case of arrays. If the object `x' is an array, then the data
+ type of the array will be returned. otherwise `_typeof' returns
+ the data type of `x'.
+
+ EXAMPLE
+
+ if (Integer_Type == _typeof (x))
+ message ("x is an integer or an integer array");
+
+
+ SEE ALSO
+ typeof, array_info, _slang_guess_type, typecast
+--------------------------------------------------------------
+
+atof
+
+ SYNOPSIS
+ Convert a string to a double precision number
+
+ USAGE
+ Double_Type atof (String_Type s)
+
+ DESCRIPTION
+ This function converts a string `s' to a double precision value
+ and returns the result. It performs no error checking on the format
+ of the string. The function `_slang_guess_type' may be used to
+ check the syntax of the string.
+
+ EXAMPLE
+
+ define error_checked_atof (s)
+ {
+ switch (_slang_guess_type (s))
+ {
+ case Double_Type:
+ return atof (s);
+ }
+ {
+ case Integer_Type:
+ return double (integer (s));
+ }
+
+ verror ("%s is not a double", s);
+ }
+
+
+ SEE ALSO
+ typecast, double, _slang_guess_type
+--------------------------------------------------------------
+
+char
+
+ SYNOPSIS
+ Convert an ascii value into a string
+
+ USAGE
+ String_Type char (Integer_Type c)
+
+ DESCRIPTION
+ The `char' function converts an integer ascii value `c' to a string
+ of unit length such that the first character of the string is `c'.
+ For example, `char('a')' returns the string `"a"'.
+
+ SEE ALSO
+ integer, string, typedef
+--------------------------------------------------------------
+
+define_case
+
+ SYNOPSIS
+ Define upper-lower case conversion.
+
+ USAGE
+ define_case (Integer_Type ch_up, Integer_Type ch_low);
+
+ DESCRIPTION
+ This function defines an upper and lowercase relationship between two
+ characters specified by the arguments. This relationship is used by
+ routines which perform uppercase and lowercase conversions.
+ The first integer `ch_up' is the ascii value of the uppercase character
+ and the second parameter `ch_low' is the ascii value of its
+ lowercase counterpart.
+
+ SEE ALSO
+ strlow, strup
+--------------------------------------------------------------
+
+double
+
+ SYNOPSIS
+ Convert an object to double precision
+
+ USAGE
+ result = double (x)
+
+ DESCRIPTION
+ The `double' function typecasts an object `x' to double
+ precision. For example, if `x' is an array of integers, an
+ array of double types will be returned. If an object cannot be
+ converted to `Double_Type', a type-mismatch error will result.
+
+ NOTES
+ The `double' function is equivalent to the typecast operation
+
+ typecast (x, Double_Type)
+
+ To convert a string to a double precision number, use the `atof'
+ function.
+
+ SEE ALSO
+ typecast, atof, int
+--------------------------------------------------------------
+
+int
+
+ SYNOPSIS
+ Typecast an object to an integer
+
+ USAGE
+ int (s)
+
+ DESCRIPTION
+ This function performs a typecast of `s' from its data type to
+ an object of `Integer_Type'. If `s' is a string, it returns
+ returns the ascii value of the first character of the string
+ `s'. If `s' is `Double_Type', `int' truncates the
+ number to an integer and returns it.
+
+ EXAMPLE
+ `int' can be used to convert single character strings to
+ integers. As an example, the intrinsic function `isdigit' may
+ be defined as
+
+ define isdigit (s)
+ {
+ if ((int (s) >= '0') and (int (s) <= '9')) return 1;
+ return 0;
+ }
+
+
+ NOTES
+ This function is equalent to `typecast (s, Integer_Type)';
+
+ SEE ALSO
+ typecast, double, integer, char, isdigit
+--------------------------------------------------------------
+
+integer
+
+ SYNOPSIS
+ Convert a string to an integer
+
+ USAGE
+ Integer_Type integer (String_Type s)
+
+ DESCRIPTION
+ The `integer' function converts a string representation of an
+ integer back to an integer. If the string does not form a valid
+ integer, a type-mismatch error will be generated.
+
+ EXAMPLE
+ `integer ("1234")' returns the integer value `1234'.
+
+ NOTES
+ This function operates only on strings and is not the same as the
+ more general `typecast' operator.
+
+ SEE ALSO
+ typecast, _slang_guess_type, string, sprintf, char
+--------------------------------------------------------------
+
+isdigit
+
+ SYNOPSIS
+ Tests for a decimal digit character
+
+ USAGE
+ Integer_Type isdigit (String_Type s)
+
+ DESCRIPTION
+ This function returns a non-zero value if the first character in the
+ string `s' is a digit; otherwise, it returns zero.
+
+ EXAMPLE
+ A simple, user defined implementation of `isdigit' is
+
+ define isdigit (s)
+ {
+ return ((s[0] <= '9') and (s[0] >= '0'));
+ }
+
+ However, the intrinsic function `isdigit' executes many times faster
+ than the equivalent representation defined above.
+
+ NOTES
+ Unlike the C function with the same name, the S-Lang function takes
+ a string argument.
+
+ SEE ALSO
+ int, integer
+--------------------------------------------------------------
+
+string
+
+ SYNOPSIS
+ Convert an object to a string representation.
+
+ USAGE
+ Integer_Type string (obj)
+
+ DESCRIPTION
+ The `string' function may be used to convert an object
+ `obj' of any type to a string representation.
+ For example, `string(12.34)' returns `"12.34"'.
+
+ EXAMPLE
+
+ define print_anything (anything)
+ {
+ message (string (anything));
+ }
+
+
+ NOTES
+ This function is _not_ the same as typecasting to a `String_Type'
+ using the `typecast' function.
+
+ SEE ALSO
+ typecast, sprintf, integer, char
+--------------------------------------------------------------
+
+tolower
+
+ SYNOPSIS
+ Convert a character to lowercase.
+
+ USAGE
+ Integer_Type lower (Integer_Type ch)
+
+ DESCRIPTION
+ This function takes an integer `ch' and returns its lowercase
+ equivalent.
+
+ SEE ALSO
+ toupper, strup, strlow, int, char, define_case
+--------------------------------------------------------------
+
+toupper
+
+ SYNOPSIS
+ Convert a character to uppercase.
+
+ USAGE
+ Integer_Type toupper (Integer_Type ch)
+
+ DESCRIPTION
+ This function takes an integer `ch' and returns its uppercase
+ equivalent.
+
+ SEE ALSO
+ tolower, strup, strlow, int, char, define_case
+--------------------------------------------------------------
+
+typecast
+
+ SYNOPSIS
+ Convert an object from one data type to another.
+
+ USAGE
+ typecast (x, new_type)
+
+ DESCRIPTION
+ The `typecast' function performs a generic typecast operation on
+ `x' to convert it to `new_type'. If `x' represents an
+ array, the function will attempt to convert all elements of `x'
+ to `new_type'. Not all objects can be converted and a
+ type-mismatch error will result upon failure.
+
+ EXAMPLE
+
+ define to_complex (x)
+ {
+ return typecast (x, Complex_Type);
+ }
+
+ defines a function that converts its argument, `x' to a complex
+ number.
+
+ SEE ALSO
+ int, double, typeof
+--------------------------------------------------------------
+
+typeof
+
+ SYNOPSIS
+ Get the data type of an object.
+
+ USAGE
+ DataType_Type typeof (x)
+
+ DESCRIPTION
+ This function returns the data type of `x'.
+
+ EXAMPLE
+
+ if (Integer_Type == typeof (x)) message ("x is an integer");
+
+
+ SEE ALSO
+ _typeof, is_struct_type, array_info, _slang_guess_type, typecast
+--------------------------------------------------------------
+
diff --git a/libslang/doc/tm/Makefile b/libslang/doc/tm/Makefile
new file mode 100644
index 0000000..e4d1a27
--- /dev/null
+++ b/libslang/doc/tm/Makefile
@@ -0,0 +1,100 @@
+# -*- sh -*-
+#
+# To create the SGML files, you will need to install the tm-utils
+# package. See http://www.jedsoft.org/ for more information.
+#
+TM2SGML = /aluche/d1/web/tm-dist/bin/tmexpand
+MACRODIR = /aluche/d1/web/tm-dist/macros
+
+TXT_FILES = slang.txt cslang.txt cref.txt slangfun.txt
+SGML_FILES = slang.sgml cslang.sgml cref.sgml slangfun.sgml
+HTML_FILES = slang.html cslang.html cref.html slangfun.html
+TEX_FILES = slang.tex cslang.tex #cref.tex slangfun.tex
+PS_FILES = slang.ps cslang.ps #cref.ps slangfun.ps
+PDF_FILES = slang.pdf cslang.pdf
+
+SGML2LATEX = sgml2latex -p letter -o tex
+SGML2HTML = sgml2html
+SGML2TXT = sgml2txt -f
+TM2TXT = tools/$(ARCH)objs/tm2txt --quiet
+LATEX = latex
+PDFLATEX = pdflatex
+
+TEXTDIR = ../text
+PSDIR = ../ps
+HTMLDIR = ../html
+SGMLDIR = ../sgml
+
+SUBDIRS = $(TEXTDIR) $(HTMLDIR) $(PSDIR) $(SGMLDIR)
+SRCDIR = `pwd`
+
+all: $(SGML_FILES) $(HTML_FILES) $(TEX_FILES) $(TXT_FILES)
+text-files: $(TXT_FILES)
+#----- SGML Files -----------------------------------------------------------
+cslang.sgml : cslang.tm preface.tm copyright.tm
+ $(TM2SGML) -I$(MACRODIR) cslang.tm cslang.sgml
+slang.sgml : slang.tm preface.tm copyright.tm
+ $(TM2SGML) -I$(MACRODIR) slang.tm slang.sgml
+cref.sgml : cref.tm
+ $(TM2SGML) -I$(MACRODIR) cref.tm cref.sgml
+slangfun.sgml : slangfun.tm
+ $(TM2SGML) -I$(MACRODIR) slangfun.tm slangfun.sgml
+#----- HTML Files -----------------------------------------------------------
+cslang.html : cslang.sgml
+ $(SGML2HTML) cslang.sgml
+slang.html : slang.sgml
+ $(SGML2HTML) slang.sgml
+cref.html : cref.sgml
+ $(SGML2HTML) cref.sgml
+slangfun.html : slangfun.sgml
+ $(SGML2HTML) slangfun.sgml
+#----- TeX Files ------------------------------------------------------------
+slang.tex : slang.sgml
+ $(SGML2LATEX) slang.sgml
+ jed -script ./fixtex.sl slang.tex
+cslang.tex : cslang.sgml
+ $(SGML2LATEX) cslang.sgml
+ jed -script ./fixtex.sl cslang.tex
+#----- PDF Files -----------------------------------------------------------
+cslang.pdf : cslang.tex
+ $(PDFLATEX) cslang.tex
+ $(PDFLATEX) cslang.tex
+slang.pdf : slang.tex
+ $(PDFLATEX) slang.tex
+ $(PDFLATEX) slang.tex
+#----- PS Files -----------------------------------------------------------
+cslang.ps : cslang.tex
+ $(LATEX) cslang.tex
+ $(LATEX) cslang.tex
+ dvips -o cslang.ps cslang.dvi
+slang.ps : slang.tex
+ $(LATEX) slang.tex
+ $(LATEX) slang.tex
+ dvips -o slang.ps slang.dvi
+#----- Text Files -----------------------------------------------------------
+cslang.txt: cslang.sgml
+ $(SGML2TXT) cslang.sgml
+slang.txt: slang.sgml
+ $(SGML2TXT) slang.sgml
+#
+slangfun.txt : slangfun.tm $(TM2TXT)
+ cat rtl/*.tm | $(TM2TXT) > slangfun.txt
+cref.txt : cref.tm $(TM2TXT)
+ $(TM2TXT) < cref.tm > cref.txt
+$(TM2TXT) : tools/tm2txt.c
+ cd tools; make SRCDIR=$(SRCDIR)
+#----------------------------------------------------------------------------
+clean:
+ -rm -f *~ *.dvi *.log *.aux *.toc rtl/*.BAK rtl/*~ *.tmp
+distclean: clean
+ -rm -f *.html *.ps $(TXT_FILES) $(TEX_FILES) $(SGML_FILES) $(PDF_FILES)
+ cd tools; make clean
+install-txt-files: $(TXT_FILES)
+ -mv $(TXT_FILES) ../text
+
+install: all $(PS_FILES)
+ -mkdir $(SUBDIRS)
+ -mv $(TXT_FILES) ../text
+ -mv *.html ../html
+ -mv $(PS_FILES) ../ps
+ -mv $(SGML_FILES) ../sgml
diff --git a/libslang/doc/tm/copyright.tm b/libslang/doc/tm/copyright.tm
new file mode 100644
index 0000000..f82a631
--- /dev/null
+++ b/libslang/doc/tm/copyright.tm
@@ -0,0 +1,476 @@
+\chapter{Copyright}
+ The \slang library is distributed under two copyrights: the GNU
+ Genral Public License, and the Artistic License. Any program
+ that uses the interpreter must adhere to rules of one of these
+ licenses.
+
+\sect{The GNU Public License}
+#v+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+#v-
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+#v+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+#v-
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+#v+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+#v-
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+#v+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+#v-
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+#v+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+#v-
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+#v+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#v-
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+#v+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+#v-
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+#v+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+#v-
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+\sect{The Artistic License}
+#v+
+ The "Artistic License"
+
+ Preamble
+#v-
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+#v+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Reasonable copying fee" is whatever you can justify on the
+ basis of media cost, duplication charges, time of people involved,
+ and so on. (You will not be required to justify it to the
+ Copyright Holder, but only to the computing community at large
+ as a market that must bear the fee.)
+
+ "Freely Available" means that no fee is charged for the item
+ itself, though there may be fees involved in handling the item.
+ It also means that recipients of the item may redistribute it
+ under the same conditions they received it.
+#v-
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain or from the Copyright Holder. A Package
+modified in such a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+#v+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or
+ an equivalent medium, or placing the modifications on a major archive
+ site such as uunet.uu.net, or by allowing the Copyright Holder to include
+ your modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+#v-
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+#v+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+#v-
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this
+Package. You may not charge a fee for this Package itself. However,
+you may distribute this Package in aggregate with other (possibly
+commercial) programs as part of a larger (possibly commercial) software
+distribution provided that you do not advertise this Package as a
+product of your own. You may embed this Package's interpreter within
+an executable of yours (by linking); this shall be construed as a mere
+form of aggregation, provided that the complete Standard Version of the
+interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whomever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of this Package with a commercial distribution is always
+permitted provided that the use of this Package is embedded; that is,
+when no overt attempt is made to make this Package's interfaces visible
+to the end user of the commercial distribution. Such use shall not be
+construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
diff --git a/libslang/doc/tm/cref.tm b/libslang/doc/tm/cref.tm
new file mode 100644
index 0000000..527c145
--- /dev/null
+++ b/libslang/doc/tm/cref.tm
@@ -0,0 +1,3430 @@
+#i linuxdoc.tm
+
+#d slang \bf{S-lang}
+#d jed \bf{jed}
+#d slang-c-programmers-guide \em{S-Lang Library C Programmer's Guide}
+#d kw#1 \tt{$1}
+#d exmp#1 \tt{$1}
+#d var#1 \tt{$1}
+#d ldots ...
+#d chapter#1 <chapt>$1<p>
+#d preface <preface>
+#d tag#1 <tag>$1</tag>
+
+#d function#1 \sect{<bf>$1</bf>\label{$1}}<descrip>
+#d variable#1 \sect{<bf>$1</bf>\label{$1}}<descrip>
+#cd function#1 <p><bf>$1</bf>\label{$1}<p><descrip>
+#d synopsis#1 <tag> Synopsis </tag> $1
+#d keywords#1 <tag> Keywords </tag> $1
+#d usage#1 <tag> Usage </tag> <tt>$1</tt>
+#d description <tag> Description </tag>
+#d example <tag> Example </tag>
+#d notes <tag> Notes </tag>
+#d seealso#1 <tag> See Also </tag> <tt>$1</tt>
+#d documentstyle article
+#d r#1 \ref{$1}{$1}
+#d done </descrip><p>
+#d 0 \exmp{0}
+#d -1 \exmp{-1}
+#d 1 \exmp{1}
+
+\linuxdoc
+\begin{\documentstyle}
+
+\title {The \slang C Library Reference}
+\author John E. Davis, \tt{davis@space.mit.edu}
+\date \__today__
+
+\toc
+
+
+\function{SLsmg_fill_region}
+\synopsis{Fill a rectangular region with a character}
+\usage{void SLsmg_fill_region (r, c, nr, nc, ch)}
+#v+
+ int r
+ int c
+ unsigned int nr
+ unsigned int nc
+ unsigned char ch
+#v-
+\description
+ The \var{SLsmg_fill_region} function may be used to a
+ rectangular region with the character \var{ch} in the current color.
+ The rectangle's upper left corner is at row \var{r} and column
+ \var{c}, and spans \var{nr} rows and \var{nc} columns. The position
+ of the virtual cursor will be left at (\var{r}, \var{c}).
+\seealso{SLsmg_write_char, SLsmg_set_color}
+\done
+
+
+
+\function{SLsmg_set_char_set}
+\synopsis{Turn on or off line drawing characters}
+\usage{void SLsmg_set_char_set (int a);}
+\description
+ \var{SLsmg_set_char_set} may be used to select or deselect the line drawing
+ character set as the current character set. If \var{a} is non-zero,
+ the line drawing character set will be selected. Otherwise, the
+ standard character set will be selected.
+\notes
+ There is no guarantee that this function will actually enable the
+ use of line drawing characters. All it does is cause subsequent
+ characters to be rendered using the terminal's alternate character
+ set. Such character sets usually contain line drawing characters.
+\seealso{SLsmg_write_char, SLtt_get_terminfo}
+\done
+
+
+\variable{int SLsmg_Scroll_Hash_Border;}
+\synopsis{Set the size of the border for the scroll hash}
+\usage{int SLsmg_Scroll_Hash_Border = 0;}
+\description
+ This variable may be used to ignore the characters that occur at the
+ beginning and the end of a row when performing the hash calculation
+ to determine whether or not a line has scrolled. The default value
+ is zero which means that all the characters on a line will be used.
+\seealso{SLsmg_refresh}
+\done
+
+
+\function{SLsmg_suspend_smg}
+\synopsis{Suspend screen management}
+\usage{int SLsmg_suspend_smg (void)}
+\description
+ \var{SLsmg_suspend_smg} can be used to suspend the state of the
+ screen management facility during suspension of the program. Use of
+ this function will reset the display back to its default state. The
+ funtion \var{SLsmg_resume_smg} should be called after suspension.
+
+ It returns zero upon success, or \-1 upon error.
+
+ This function is similar to \var{SLsmg_reset_smg} except that the
+ state of the display prior to calling \var{SLsmg_suspend_smg} is saved.
+\seealso{SLsmg_resume_smg, SLsmg_reset_smg}
+\done
+
+
+\function{SLsmg_resume_smg}
+\synopsis{Resume screen management}
+\usage{int SLsmg_resume_smg (void)}
+\description
+ \var{SLsmg_resume_smg} should be called after
+ \var{SLsmg_suspend_smg} to redraw the display exactly like it was
+ before \var{SLsmg_suspend_smg} was called. It returns zero upon
+ success, or \-1 upon error.
+\seealso{SLsmg_suspend_smg}
+\done
+
+
+\function{SLsmg_erase_eol}
+\synopsis{Erase to the end of the row}
+\usage{void SLsmg_erase_eol (void);}
+\description
+ \var{SLsmg_erase_eol} erases all characters from the current
+ position to the end of the line. The newly created space is given
+ the color of the current color. This function has no effect on the
+ position of the virtual cursor.
+\seealso{SLsmg_gotorc, SLsmg_erase_eos, SLsmg_fill_region}
+\done
+
+
+\function{SLsmg_gotorc}
+\synopsis{Move the virtual cursor}
+\usage{void SLsmg_gotorc (int r, int c)}
+\description
+ The \var{SLsmg_gotorc} function moves the virtual cursor to the row
+ \var{r} and column \var{c}. The first row and first column is
+ specified by \exmp{r = 0} and \exmp{c = 0}.
+\seealso{SLsmg_refresh}
+\done
+
+
+\function{SLsmg_erase_eos}
+\synopsis{Erase to the end of the screen}
+\usage{void SLsmg_erase_eos (void);}
+\description
+ The \var{SLsmg_erase_eos} is like \var{SLsmg_erase_eol} except that
+ it erases all text from the current position to the end of the
+ display. The current color will be used to set the background of
+ the erased area.
+\seealso{SLsmg_erase_eol}
+\done
+
+
+\function{SLsmg_reverse_video}
+\synopsis{Set the current color to 1}
+\usage{void SLsmg_reverse_video (void);}
+\description
+ This function is nothing more than \exmp{SLsmg_set_color(1)}.
+\seealso{SLsmg_set_color}
+\done
+
+
+\function{SLsmg_set_color (int)}
+\synopsis{Set the current color}
+\usage{void SLsmg_set_color (int c);}
+\description
+ \var{SLsmg_set_color} is used to set the current color. The
+ parameter \var{c} is really a color object descriptor. Actual
+ foreground and background colors as well as other visual attributes
+ may be associated with a color descriptor via the
+ \var{SLtt_set_color} function.
+\example
+ This example defines color \exmp{7} to be green foreground on black
+ background and then displays some text in this color:
+#v+
+ SLtt_set_color (7, NULL, "green", "black");
+ SLsmg_set_color (7);
+ SLsmg_write_string ("Hello");
+ SLsmg_refresh ();
+#v-
+\notes
+ It is important to understand that the screen managment routines
+ know nothing about the actual colors associated with a color
+ descriptor. Only the descriptor itself is used by the \var{SLsmg}
+ routines. The lower level \var{SLtt} interface converts the color
+ descriptors to actual colors. Thus
+#v+
+ SLtt_set_color (7, NULL, "green", "black");
+ SLsmg_set_color (7);
+ SLsmg_write_string ("Hello");
+ SLtt_set_color (7, NULL, "red", "blue");
+ SLsmg_write_string ("World");
+ SLsmg_refresh ();
+#v-
+ will result in \exmp{"hello"} displayed in red on blue and \em{not}
+ green on black.
+\seealso{SLtt_set_color, SLtt_set_color_object}
+\done
+
+
+\function{SLsmg_normal_video}
+\synopsis{Set the current color to 0}
+\usage{void SLsmg_normal_video (void);}
+\description
+ \var{SLsmg_normal_video} sets the current color descriptor to \var{0}.
+\seealso{SLsmg_set_color}
+\done
+
+
+\function{SLsmg_printf}
+\synopsis{Format a string on the virtual display}
+\usage{void SLsmg_printf (char *fmt, ...)}
+\description
+ \var{SLsmg_printf} format a \var{printf} style variable argument
+ list and writes it on the virtual display. The virtual cursor will
+ be moved to the end of the string.
+\seealso{SLsmg_write_string, SLsmg_vprintf}
+\done
+
+
+\function{SLsmg_vprintf}
+\synopsis{Format a string on the virtual display}
+\usage{void SLsmg_vprintf (char *fmt, va_list ap)}
+\description
+ \var{SLsmg_vprintf} formats a string in the manner of \em{vprintf}
+ and writes the result to the display. The virtual cursor is
+ advanced to the end of the string.
+\seealso{SLsmg_write_string, SLsmg_printf}
+\done
+
+
+\function{SLsmg_write_string}
+\synopsis{Write a character string on the display }
+\usage{void SLsmg_write_string (char *s)}
+\description
+ The function \var{SLsmg_write_string} displays the string \var{s} on
+ the virtual display at the current position and moves the position
+ to the end of the string.
+\seealso{SLsmg_printf, SLsmg_write_nstring}
+\done
+
+
+\function{SLsmg_write_nstring}
+\synopsis{Write the first n characters of a string on the display}
+\usage{void SLsmg_write_nstring (char *s, unsigned int n);}
+\description
+ \var{SLsmg_write_nstring} writes the first \var{n} characters of
+ \var{s} to this virtual display. If the length of the string
+ \var{s} is less than \var{n}, the spaces will used until
+ \var{n} characters have been written. \var{s} can be \var{NULL}, in
+ which case \var{n} spaces will be written.
+\seealso{SLsmg_write_string, SLsmg_write_nchars}
+\done
+
+
+\function{SLsmg_write_char}
+\synopsis{Write a character to the virtual display}
+\usage{void SLsmg_write_char (char ch);}
+\description
+ \var{SLsmg_write_char} writes the character \var{ch} to the virtual
+ display.
+\seealso{SLsmg_write_nchars, SLsmg_write_string}
+\done
+
+
+\function{SLsmg_write_nchars}
+\synopsis{Write n characters to the virtual display}
+\usage{void SLsmg_write_nchars (char *s, unsigned int n);}
+\description
+ \var{SLsmg_write_nchars} writes at most \var{n} characters from the
+ string \var{s} to the display. If the length of \var{s} is less
+ than \var{n}, the whole length of the string will get written.
+
+ This function differs from \var{SLsmg_write_nstring} in that
+ \var{SLsmg_write_nstring} will pad the string to write exactly
+ \var{n} characters. \var{SLsmg_write_nchars} does not perform any
+ padding.
+\seealso{SLsmg_write_nchars, SLsmg_write_nstring}
+\done
+
+
+\function{SLsmg_write_wrapped_string}
+\synopsis{Write a string to the display with wrapping}
+\usage{void SLsmg_write_wrapped_string (s, r, c, nr, nc, fill)}
+#v+
+ char *s
+ int r, c
+ unsigned int nr, nc
+ int fill
+#v-
+\description
+ \var{SLsmg_write_wrapped_string} writes the string \var{s} to the
+ virtual display. The string will be confined to the rectangular
+ region whose upper right corner is at row \var{r} and column \var{c},
+ and consists of \var{nr} rows and \var{nc} columns. The string will
+ be wrapped at the boundaries of the box. If \var{fill} is non-zero,
+ the last line to which characters have been written will get padded
+ with spaces.
+\notes
+ This function does not wrap on word boundaries. However, it will
+ wrap when a newline charater is encountered.
+\seealso{SLsmg_write_string}
+\done
+
+
+\function{SLsmg_cls}
+\synopsis{Clear the virtual display}
+\usage{void SLsmg_cls (void)}
+\description
+ \var{SLsmg_cls} erases the virtual display using the current color.
+ This will cause the physical display to get cleared the next time
+ \var{SLsmg_refresh} is called.
+\notes
+ This function is not the same as
+#v+
+ SLsmg_gotorc (0,0); SLsmg_erase_eos ();
+#v-
+ since these statements do not guarantee that the physical screen
+ will get cleared.
+\seealso{SLsmg_refresh, SLsmg_erase_eos}
+\done
+
+
+\function{SLsmg_refresh}
+\synopsis{Update physical screen}
+\usage{void SLsmg_refresh (void)}
+\description
+ The \var{SLsmg_refresh} function updates the physical display to
+ look like the virtual display.
+\seealso{SLsmg_suspend_smg, SLsmg_init_smg, SLsmg_reset_smg}
+\done
+
+
+\function{SLsmg_touch_lines}
+\synopsis{Mark lines on the virtual display for redisplay}
+\usage{void SLsmg_touch_lines (int r, unsigned int nr)}
+\description
+ \var{SLsmg_touch_lines} marks the \var{nr} lines on the virtual
+ display starting at row \var{r} for redisplay upon the next call to
+ \var{SLsmg_refresh}.
+\notes
+ This function should rarely be called, if ever. If you find that
+ you need to call this function, then your application should be
+ modified to properly use the \var{SLsmg} screen management routines.
+ This function is provided only for curses compatibility.
+\seealso{SLsmg_refresh}
+\done
+
+\function{SLsmg_init_smg}
+\synopsis{Initialize the \var{SLsmg} routines}
+\usage{int SLsmg_init_smg (void)}
+\description
+ The \var{SLsmg_init_smg} function initializes the \var{SLsmg} screen
+ management routines. Specifically, this function allocates space
+ for the virtual display and calls \var{SLtt_init_video} to put the
+ terminal's physical display in the proper state. It is up to the
+ caller to make sure that the \var{SLtt} routines are initialized via
+ \var{SLtt_get_terminfo} before calling \var{SLsmg_init_smg}.
+
+ This function should also be called any time the size of the
+ physical display has changed so that it can reallocate a new virtual
+ display to match the physical display.
+
+ It returns zero upon success, or \-1 upon failure.
+\seealso{SLsmg_reset_smg}
+\done
+
+
+\function{SLsmg_reset_smg}
+\synopsis{Reset the \var{SLsmg} routines}
+\usage{int SLsmg_reset_smg (void);}
+\description
+ \var{SLsmg_reset_smg} resets the \var{SLsmg} screen management
+ routines by freeing all memory allocated while it was active. It
+ also calls \var{SLtt_reset_video} to put the terminal's display in
+ it default state.
+\seealso{SLsmg_init_smg}
+\done
+
+
+\function{SLsmg_char_at}
+\synopsis{Get the character at the current position on the virtual display}
+\usage{unsigned short SLsmg_char_at(void)}
+\description
+ The \var{SLsmg_char_at} function returns the character and its color
+ at the current position on the virtual display.
+\seealso{SLsmg_read_raw, SLsmg_write_char}
+\done
+
+
+\function{SLsmg_set_screen_start}
+\synopsis{Set the origin of the virtual display}
+\usage{void SLsmg_set_screen_start (int *r, int *c)}
+\description
+ \var{SLsmg_set_screen_start} sets the origin of the virtual display
+ to the row \var{*r} and the column \var{*c}. If either \var{r} or \var{c}
+ is \var{NULL}, then the corresponding value will be set to \var{0}.
+ Otherwise, the location specified by the pointers will be updated to
+ reflect the old origin.
+
+ See \tt{slang/demo/pager.c} for how this function may be used to
+ scroll horizontally.
+\seealso{SLsmg_init_smg}
+\done
+
+
+\function{SLsmg_draw_hline}
+\synopsis{Draw a horizontal line}
+\usage{void SLsmg_draw_hline (unsigned int len)}
+\description
+ The \var{SLsmg_draw_hline} function draws a horizontal line of
+ length \var{len} on the virtual display. The position of the
+ virtual cursor is left at the end of the line.
+\seealso{SLsmg_draw_vline}
+\done
+
+
+\function{SLsmg_draw_vline}
+\synopsis{Draw a vertical line}
+\usage{void SLsmg_draw_vline (unsigned int len);}
+\description
+ The \var{SLsmg_draw_vline} function draws a vertical line of
+ length \var{len} on the virtual display. The position of the
+ virtual cursor is left at the end of the line.
+\seealso{??}
+\done
+
+
+\function{SLsmg_draw_object}
+\synopsis{Draw an object from the alternate character set}
+\usage{void SLsmg_draw_object (int r, int c, unsigned char obj)}
+\description
+ The \var{SLsmg_draw_object} function may be used to place the object
+ specified by \var{obj} at row \var{r} and column \var{c}. The
+ object is really a character from the alternate character set and
+ may be specified using one of the following constants:
+#v+
+ SLSMG_HLINE_CHAR Horizontal line
+ SLSMG_VLINE_CHAR Vertical line
+ SLSMG_ULCORN_CHAR Upper left corner
+ SLSMG_URCORN_CHAR Upper right corner
+ SLSMG_LLCORN_CHAR Lower left corner
+ SLSMG_LRCORN_CHAR Lower right corner
+ SLSMG_CKBRD_CHAR Checkboard character
+ SLSMG_RTEE_CHAR Right Tee
+ SLSMG_LTEE_CHAR Left Tee
+ SLSMG_UTEE_CHAR Up Tee
+ SLSMG_DTEE_CHAR Down Tee
+ SLSMG_PLUS_CHAR Plus or Cross character
+#v-
+\seealso{SLsmg_draw_vline, SLsmg_draw_hline, SLsmg_draw_box}
+\done
+
+
+\function{SLsmg_draw_box}
+\synopsis{Draw a box on the virtual display}
+\usage{void SLsmg_draw_box (int r, int c, unsigned int dr, unsigned int dc)}
+\description
+ \var{SLsmg_draw_box} uses the \var{SLsmg_draw_hline} and
+ \var{SLsmg_draw_vline} functions to draw a rectangular box on the
+ virtual display. The box's upper left corner is placed at row
+ \var{r} and column \var{c}. The width and length of the box is
+ specified by \var{dc} and \var{dr}, respectively.
+\seealso{SLsmg_draw_vline, SLsmg_draw_hline, SLsmg_draw_object}
+\done
+
+\function{SLsmg_set_color_in_region}
+\synopsis{Change the color of a specifed region}
+\usage{void SLsmg_set_color_in_region (color, r, c, dr, dc)}
+#v+
+ int color;
+ int r, c;
+ unsigned int dr, dc;
+#v-
+\description
+ \var{SLsmg_set_color_in_region} may be used to change the color of a
+ rectangular region whose upper left corner is given by
+ (\var{r},\var{c}), and whose width and height is given by \var{dc}
+ and \var{dr}, respectively. The color of the region is given by the
+ \var{color} parameter.
+\seealso{SLsmg_draw_box, SLsmg_set_color}
+\done
+
+
+\function{SLsmg_get_column}
+\synopsis{Get the column of the virtual cursor}
+\usage{int SLsmg_get_column(void);}
+\description
+ The \var{SLsmg_get_column} function returns the current column of
+ the virtual cursor on the virtual display.
+\seealso{SLsmg_get_row, SLsmg_gotorc}
+\done
+
+
+\function{SLsmg_get_row}
+\synopsis{Get the row of the virtual cursor}
+\usage{int SLsmg_get_row(void);}
+\description
+ The \var{SLsmg_get_row} function returns the current row of the
+ virtual cursor on the virtual display.
+\seealso{SLsmg_get_column, SLsmg_gotorc}
+\done
+
+
+\function{SLsmg_forward}
+\synopsis{Move the virtual cursor forward n columns}
+\usage{void SLsmg_forward (int n);}
+\description
+ The \var{SLsmg_forward} function moves the virtual cursor forward
+ \var{n} columns.
+\seealso{SLsmg_gotorc}
+\done
+
+
+\function{SLsmg_write_color_chars}
+\synopsis{Write characters with color descriptors to virtual display}
+\usage{void SLsmg_write_color_chars (unsigned short *s, unsigned int len)}
+\description
+ The \var{SLsmg_write_color_chars} function may be used to write
+ \var{len} characters, each with a different color descriptor to the
+ virtual display. Each character and its associated color are
+ encoded as an \exmp{unsigned short} such that the lower eight bits
+ form the character and the next eight bits form the color.
+\seealso{SLsmg_char_at, SLsmg_write_raw}
+\done
+
+
+\function{SLsmg_read_raw}
+\synopsis{Read characters from the virtual display}
+\usage{unsigned int SLsmg_read_raw (unsigned short *buf, unsigned int len)}
+\description
+ \var{SLsmg_read_raw} attempts to read \var{len} characters from the
+ current position on the virtual display into the buffer specified by
+ \var{buf}. It returns the number of characters actually read. This
+ number will be less than \var{len} if an attempt is made to read
+ past the right margin of the display.
+\notes
+ The purpose of the pair of functions, \var{SLsmg_read_raw} and
+ \var{SLsmg_write_raw}, is to permit one to copy the contents of one
+ region of the virtual display to another region.
+\seealso{SLsmg_char_at, SLsmg_write_raw}
+\done
+
+
+\function{SLsmg_write_raw}
+\synopsis{Write characters directly to the virtual display}
+\usage{unsigned int SLsmg_write_raw (unsigned short *buf, unsigned int len)}
+\description
+ The \var{SLsmg_write_raw} function attempts to write \var{len}
+ characters specified by \var{buf} to the display at the current
+ position. It returns the number of characters successfully written,
+ which will be less than \var{len} if an attempt is made to write
+ past the right margin.
+\notes
+ The purpose of the pair of functions, \var{SLsmg_read_raw} and
+ \var{SLsmg_write_raw}, is to permit one to copy the contents of one
+ region of the virtual display to another region.
+\seealso{SLsmg_read_raw}
+\done
+
+
+\function{SLallocate_load_type}
+\synopsis{Allocate a SLang_Load_Type object}
+\usage{SLang_Load_Type *SLallocate_load_type (char *name)}
+\description
+ The \var{SLallocate_load_type} function allocates and initializes
+ space for a \var{SLang_Load_Type} object and returns it. Upon
+ failure, the function returns \var{NULL}. The parameter \var{name}
+ must uniquely identify the object. For example, if the object
+ represents a file, then \var{name} could be the absolute path name
+ of the file.
+\seealso{SLdeallocate_load_type, SLang_load_object}
+\done
+
+\function{SLdeallocate_load_type}
+\synopsis{Free a SLang_Load_Type object}
+\usage{void SLdeallocate_load_type (SLang_Load_Type *slt)}
+\description
+ This function frees the memory associated with a
+ \var{SLang_Load_Type} object that was acquired from a call to the
+ \var{SLallocate_load_type} function.
+\seealso{SLallocate_load_type, SLang_load_object}
+\done
+
+
+\function{SLang_load_object}
+\synopsis{Load an object into the interpreter}
+\usage{int SLang_load_object (SLang_Load_Type *obj)}
+\description
+ The function \var{SLang_load_object} is a generic function that may
+ be used to loaded an object of type \var{SLang_Load_Type} into the
+ interpreter. For example, the functions \var{SLang_load_file} and
+ \var{SLang_load_string} are wrappers around this function to load a
+ file and a string, respectively.
+\seealso{SLang_load_file, SLang_load_string, SLallocate_load_type}
+\done
+
+
+\function{SLclass_allocate_class}
+\synopsis{Allocate a class for a new data type}
+\usage{SLang_Class_Type *SLclass_allocate_class (char *name)}
+\description
+ The purpose of this function is to allocate and initialize space
+ that defines a new data type or class called \var{name}. If
+ successful, a pointer to the class is returned, or upon failure the
+ function returns \var{NULL}.
+
+ This function does not automatically create the new data type.
+ Callback functions must first be associated with the data type via
+ functions such as \var{SLclass_set_push_function}, and the data
+ type must be registered with the interpreter via
+ \var{SLclass_register_class}. See the \slang library programmer's
+ guide for more information.
+\seealso{SLclass_register_class, SLclass_set_push_function}
+\done
+
+
+\function{SLclass_register_class}
+\synopsis{Register a new data type with the interpreter}
+\usage{int SLclass_register_class (cl, type, sizeof_type, class_type)}
+#v+
+ SLang_Class_Type *cl
+ unsigned char type
+ unsigned int sizeof_type
+ unsigned char class_type
+#v-
+\description
+ The \var{SLclass_register_class} function is used to register a new
+ class or data type with the interpreter. If successful, the
+ function returns \exmp{0}, or upon failure, it returns \var{-1}.
+
+ The first parameter, \var{cl}, must have been previously obtained
+ via the \var{SLclass_allocate_class} function.
+
+ The second parameter, \var{type} specifies the data type of the new
+ class. It must be an unsigned character with value greater that
+ \exmp{127}. The values in the range \exmp{0-127} are reserved for
+ internal use by the library.
+
+ The size that the data type represents in bytes is specified by the
+ third parameter, \var{sizeof_type}. This value should not be
+ confused with the sizeof the structure that represents the data
+ type, unless the data type is of class \var{SLANG_CLASS_TYPE_VECTOR}
+ or \var{SLANG_CLASS_TYPE_SCALAR}. For pointer objects, the value
+ of this parameter is just \var{sizeof(void *)}.
+
+ The final parameter specifies the class type of the data type. It must
+ be one of the values:
+#v+
+ SLANG_CLASS_TYPE_SCALAR
+ SLANG_CLASS_TYPE_VECTOR
+ SLANG_CLASS_TYPE_PTR
+ SLANG_CLASS_TYPE_MMT
+#v-
+ The \var{SLANG_CLASS_TYPE_SCALAR} indicates that the new data type
+ is a scalar. Examples of scalars in \var{SLANG_INT_TYPE} and
+ \var{SLANG_DOUBLE_TYPE}.
+
+ Setting \var{class_type} to SLANG_CLASS_TYPE_VECTOR implies that the
+ new data type is a vector, or a 1-d array of scalar types. An
+ example of a data type of this class is the
+ \var{SLANG_COMPLEX_TYPE}, which represents complex numbers.
+
+ \var{SLANG_CLASS_TYPE_PTR} specifies the data type is of a pointer
+ type. Examples of data types of this class include
+ \var{SLANG_STRING_TYPE} and \var{SLANG_ARRAY_TYPE}. Such types must
+ provide for their own memory management.
+
+ Data types of class \var{SLANG_CLASS_TYPE_MMT} are pointer types
+ except that the memory management, i.e., creation and destruction of
+ the type, is handled by the interpreter. Such a type is called a
+ \em{memory managed type}. An example of this data type is the
+ \var{SLANG_FILEPTR_TYPE}.
+\notes
+ See the \slang-c-programmers-guide for more information.
+\seealso{SLclass_allocate_class}
+\done
+
+
+\function{SLclass_set_string_function}
+\synopsis{Set a data type's string representation callback}
+\usage{int SLclass_set_string_function (cl, sfun)}
+#v+
+ SLang_Class_Type *cl
+ char *(*sfun) (unsigned char, VOID_STAR);
+#v-
+\description
+ The \var{SLclass_set_string_function} routine is used to define a
+ callback function, \var{sfun}, that will be used when a string
+ representation of an object of the data type represented by \var{cl}
+ is needed. \var{cl} must have already been obtained via a call to
+ \var{SLclass_allocate_class}. When called, \var{sfun} will be
+ passed two arguments: a unsigned char which represents the data
+ type, and the address of the object for which a string represetation
+ is required. The callback function must return a \em{malloced}
+ string.
+
+ Upon success, \var{SLclass_set_string_function} returns zero, or
+ upon error it returns \-1.
+\example
+ A callback function that handles both \var{SLANG_STRING_TYPE} and
+ \var{SLANG_INT_TYPE} variables looks like:
+#v+
+ char *string_and_int_callback (unsigned char type, VOID_STAR addr)
+ {
+ char buf[64];
+
+ switch (type)
+ {
+ case SLANG_STRING_TYPE:
+ return SLmake_string (*(char **)addr);
+
+ case SLANG_INTEGER_TYPE:
+ sprintf (buf, "%d", *(int *)addr);
+ return SLmake_string (buf);
+ }
+ return NULL;
+ }
+#v-
+\notes
+ The default string callback simply returns the name of the data type.
+\seealso{SLclass_allocate_class, SLclass_register_class}
+\done
+
+
+\function{SLclass_set_destroy_function}
+\synopsis{Set the destroy method callback for a data type}
+\usage{int SLclass_set_destroy_function (cl, destroy_fun)}
+#v+
+ SLang_Class_Type *cl
+ void (*destroy_fun) (unsigned char, VOID_STAR);
+#v-
+\description
+ \var{SLclass_set_destroy_function} is used to set the destroy
+ callback for a data type. The data type's class \var{cl} must have
+ been previously obtained via a call to \var{SLclass_allocate_class}.
+ When called, \var{destroy_fun} will be passed two arguments: a
+ unsigned char which represents the data type, and the address of the
+ object to be destroyed.
+
+ \var{SLclass_set_destroy_function} returns zero upon success, and
+ \-1 upon failure.
+\example
+ The destroy method for \var{SLANG_STRING_TYPE} looks like:
+#v+
+ static void string_destroy (unsigned char type, VOID_STAR ptr)
+ {
+ char *s = *(char **) ptr;
+ if (s != NULL) SLang_free_slstring (*(char **) s);
+ }
+#v-
+\notes
+ Data types of class SLANG_CLASS_TYPE_SCALAR do not require a destroy
+ callback. However, other classes do.
+\seealso{SLclass_allocate_class, SLclass_register_class}
+\done
+
+
+\function{SLclass_set_push_function}
+\synopsis{Set the push callback for a new data type}
+\usage{int SLclass_set_push_function (cl, push_fun)}
+#v+
+ SLang_Class_Type *cl
+ int (*push_fun) (unsigned char, VOID_STAR);
+#v-
+\description
+ \var{SLclass_set_push_function} is used to set the push callback
+ for a new data type specified by \var{cl}, which must have been
+ previously obtained via \var{SLclass_allocate_class}.
+
+ The parameter \var{push_fun} is a pointer to the push callback. It
+ is required to take two arguments: an unsigned character
+ representing the data type, and the address of the object to be
+ pushed. It must return zero upon success, or \-1 upon failure.
+
+ \var{SLclass_set_push_function} returns zero upon success, or \-1
+ upon failure.
+\example
+ The push callback for \var{SLANG_COMPLEX_TYPE} looks like:
+#v+
+ static int complex_push (unsigned char type, VOID_STAR ptr)
+ {
+ double *z = *(double **) ptr;
+ return SLang_push_complex (z[0], z[1]);
+ }
+#v-
+\seealso{SLclass_allocate_class, SLclass_register_class}
+\done
+
+
+\function{SLclass_set_pop_function}
+\synopsis{Set the pop callback for a new data type}
+\usage{int SLclass_set_pop_function (cl, pop_fun)}
+#v+
+ SLang_Class_Type *cl
+ int (*pop_fun) (unsigned char, VOID_STAR);
+#v-
+\description
+ \var{SLclass_set_pop_function} is used to set the callback for
+ popping an object from the stack for a new data type specified by
+ \var{cl}, which must have been previously obtained via
+ \var{SLclass_allocate_class}.
+
+ The parameter \var{pop_fun} is a pointer to the pop callback
+ function, which is required to take two arguments: an unsigned
+ character representing the data type, and the address of the object
+ to be popped. It must return zero upon success, or \-1 upon
+ failure.
+
+ \var{SLclass_set_pop_function} returns zero upon success, or \-1
+ upon failure.
+\example
+ The pop callback for \var{SLANG_COMPLEX_TYPE} looks like:
+#v+
+ static int complex_push (unsigned char type, VOID_STAR ptr)
+ {
+ double *z = *(double **) ptr;
+ return SLang_pop_complex (&z[0], &z[1]);
+ }
+#v-
+\seealso{SLclass_allocate_class, SLclass_register_class}
+\done
+
+
+\function{SLclass_get_datatype_name}
+\synopsis{Get the name of a data type}
+\usage{char *SLclass_get_datatype_name (unsigned char type)}
+\description
+ The \var{SLclass_get_datatype_name} function returns the name of the
+ data type specified by \var{type}. For example, if \var{type} is
+ \var{SLANG_INT_TYPE}, the string \exmp{"Integer_Type"} will be
+ returned.
+
+ This function returns a pointer that should not be modified or freed.
+\seealso{SLclass_allocate_class, SLclass_register_class}
+\done
+
+\function{SLang_free_mmt}
+\synopsis{Free a memory managed type}
+\usage{void SLang_free_mmt (SLang_MMT_Type *mmt)}
+\description
+ The \var{SLang_MMT_Type} function is used to free a memory managed
+ data type.
+\seealso{SLang_object_from_mmt, SLang_create_mmt}
+\done
+
+
+\function{SLang_object_from_mmt}
+\synopsis{Get a pointer to the value of a memory managed type}
+\usage{VOID_STAR SLang_object_from_mmt (SLang_MMT_Type *mmt)}
+\description
+ The \var{SLang_object_from_mmt} function returns a pointer to the
+ actual object whose memory is being managed by the interpreter.
+\seealso{SLang_free_mmt, SLang_create_mmt}
+\done
+
+
+\function{SLang_create_mmt}
+\synopsis{Create a memory managed data type}
+\usage{SLang_MMT_Type *SLang_create_mmt (unsigned char t, VOID_STAR ptr)}
+\description
+ The \var{SLang_create_mmt} function returns a pointer to a new
+ memory managed object. This object contains information necessary
+ to manage the memory associated with the pointer \var{ptr} which
+ represents the application defined data type of type \var{t}.
+\seealso{SLang_object_from_mmt, SLang_push_mmt, SLang_free_mmt}
+\done
+
+
+\function{SLang_push_mmt}
+\synopsis{Push a memory managed type}
+\usage{int SLang_push_mmt (SLang_MMT_Type *mmt)}
+\description
+ This function is used to push a memory managed type onto the
+ interpreter stack. It returns zero upon success, or \exmp{-1} upon
+ failure.
+\seealso{SLang_create_mmt, SLang_pop_mmt}
+\done
+
+
+\function{SLang_pop_mmt}
+\synopsis{Pop a memory managed data type}
+\usage{SLang_MMT_Type *SLang_pop_mmt (unsigned char t)}
+\description
+ The \var{SLang_pop_mmt} function may be used to pop a memory managed
+ type of type \var{t} from the stack. It returns a pointer to the
+ memory managed object upon success, or \var{NULL} upon failure. The
+ function \var{SLang_object_from_mmt} should be used to access the
+ actual pointer to the data type.
+\seealso{SLang_object_from_mmt, SLang_push_mmt}
+\done
+
+
+\function{SLang_inc_mmt}
+\synopsis{Increment a memory managed type reference count}
+\usage{void SLang_inc_mmt (SLang_MMT_Type *mmt);}
+\description
+ The \var{SLang_inc_mmt} function may be used to increment the
+ reference count associated with the memory managed data type given
+ by \var{mmt}.
+\seealso{SLang_free_mmt, SLang_create_mmt, SLang_pop_mmt, SLang_pop_mmt}
+\done
+
+
+\function{SLang_vmessage}
+\synopsis{Display a message to the message device}
+\usage{void SLang_vmessage (char *fmt, ...)}
+\description
+ This function prints a \var{printf} style formatted variable
+ argument list to the message device. The default message device is
+ \var{stdout}.
+\seealso{SLang_verror}
+\done
+
+
+\function{SLang_exit_error}
+\synopsis{Exit the program and display an error message}
+\usage{void SLang_exit_error (char *fmt, ...)}
+\description
+ The \var{SLang_exit_error} function terminates the program and
+ displays an error message using a \var{printf} type variable
+ argument list. The default behavior to this function is to write
+ the message to \var{stderr} and exit with the \var{exit} system
+ call.
+
+ If the function pointer \var{SLang_Exit_Error_Hook} is
+ non-NULL, the function to which it points will be called. This
+ permits an application to perform whatever cleanup is necessary.
+ This hook has the prototype:
+#v+
+ void (*SLang_Exit_Error_Hook)(char *, va_list);
+#v-
+\seealso{SLang_verror, exit}
+\done
+
+
+\function{SLang_init_slang}
+\synopsis{Initialize the interpreter}
+\usage{int SLang_init_slang (void)}
+\description
+ The \var{SLang_init_slang} function must be called by all
+ applications that use the \slang interpreter. It initializes the
+ interpreter, defines the built-in data types, and adds a set of core
+ intrinsic functions.
+
+ The function returns \var{0} upon success, or \var{-1} upon failure.
+\seealso{SLang_init_slfile, SLang_init_slmath, SLang_init_slunix}
+\done
+
+\function{SLang_init_slfile}
+\synopsis{Initialize the interpreter file I/O intrinsics}
+\usage{int SLang_init_slfile (void)}
+\description
+ This function initializes the interpreters file I/O intrinsic
+ functions. This function adds intrinsic functions such as
+ \var{fopen}, \var{fclose}, and \var{fputs} to the interpreter.
+ It returns \exmp{0} if successful, or \exmp{-1} upon error.
+\notes
+ Before this function can be called, it is first necessary to call
+ \var{SLang_init_slang}. It also adds
+ the preprocessor symbol \var{__SLFILE__} to the interpreter.
+\seealso{SLang_init_slang, SLang_init_slunix, SLang_init_slmath}
+\done
+
+
+\function{SLang_init_slmath}
+\synopsis{Initialize the interpreter math intrinsics}
+\usage{int SLang_init_slmath (void)}
+\description
+ The \var{SLang_init_slmath} function initializes the interpreter's
+ mathematical intrinsic functions and makes them available to the
+ language. The intrinsic functions include \var{sin}, \var{cos},
+ \var{tan}, etc... It returns \exmp{0} if successful, or \exmp{-1}
+ upon failure.
+\notes
+ This function must be called after \var{SLang_init_slang}. It adds
+ the preprocessor symbol \var{__SLMATH__} to the interpreter.
+\seealso{SLang_init_slang, SLang_init_slfile, SLang_init_slunix}
+\done
+
+
+\function{SLang_init_slunix}
+\synopsis{Make available some unix system calls to the interpreter}
+\usage{int SLang_init_slunix (void)}
+\description
+ The \var{SLang_init_slunix} function initializes the interpreter's
+ unix system call intrinsic functions and makes them available to the
+ language. Examples of functions made available by
+ \var{SLang_init_slunix} include \var{chmod}, \var{chown}, and
+ \var{stat_file}. It returns \exmp{0} if successful, or \exmp{-1}
+ upon failure.
+\notes
+ This function must be called after \var{SLang_init_slang}. It adds
+ the preprocessor symbol \var{__SLUNIX__} to the interpreter.
+\seealso{SLang_init_slang, SLang_init_slfile, SLang_init_slmath}
+\done
+
+
+\function{SLadd_intrin_fun_table}
+\synopsis{Add a table of intrinsic functions to the interpreter}
+\usage{int SLadd_intrin_fun_table(SLang_Intrin_Fun_Type *tbl, char *pp_name);}
+\description
+ The \var{SLadd_intrin_fun_table} function adds an array, or table, of
+ \var{SLang_Intrin_Fun_Type} objects to the interpreter. The first
+ parameter, \var{tbl} specifies the table to be added. The second
+ parameter \var{pp_name}, if non-NULL will be added to the list of
+ preprocessor symbols.
+
+ This function returns \-1 upon failure or zero upon success.
+\notes
+ A table should only be loaded one time and it is considered to be an
+ error on the part of the application if it loads a table more than
+ once.
+\seealso{SLadd_intrin_var_table, SLadd_intrinsic_function, SLdefine_for_ifdef}
+\done
+
+\function{SLadd_intrin_var_table}
+\synopsis{Add a table of intrinsic variables to the interpreter}
+\usage{int SLadd_intrin_var_table (SLang_Intrin_Var_Type *tbl, char *pp_name);}
+\description
+ The \var{SLadd_intrin_var_table} function adds an array, or table, of
+ \var{SLang_Intrin_Var_Type} objects to the interpreter. The first
+ parameter, \var{tbl} specifies the table to be added. The second
+ parameter \var{pp_name}, if non-NULL will be added to the list of
+ preprocessor symbols.
+
+ This function returns \-1 upon failure or zero upon success.
+\notes
+ A table should only be loaded one time and it is considered to be an
+ error on the part of the application if it loads a table more than
+ once.
+\seealso{SLadd_intrin_var_table, SLadd_intrinsic_function, SLdefine_for_ifdef}
+\done
+
+
+\function{SLang_load_file}
+\synopsis{Load a file into the interpreter}
+\usage{int SLang_load_file (char *fn)}
+\description
+ The \var{SLang_load_file} function opens the file whose name is
+ specified by \var{fn} and feeds it to the interpreter, line by line,
+ for execution. If \var{fn} is \var{NULL}, the function will take
+ input from \var{stdin}.
+
+ If no error occurs, it returns \exmp{0}; otherwise,
+ it returns \exmp{-1}, and sets \var{SLang_Error} accordingly. For
+ example, if it fails to open the file, it will return \exmp{-1} with
+ \var{SLang_Error} set to \var{SL_OBJ_NOPEN}.
+\notes
+ If the hook \var{SLang_Load_File_Hook} declared as
+#v+
+ int (*SLang_Load_File_Hook)(char *);
+#v-
+ is non-NULL, the function point to by it will be used to load the
+ file. For example, the \jed editor uses this hook to load files
+ via its own routines.
+\seealso{SLang_load_object, SLang_load_string}
+\done
+
+
+\function{SLang_restart}
+\synopsis{Reset the interpreter after an error}
+\usage{void SLang_restart (int full)}
+\description
+ The \var{SLang_restart} function should be called by the
+ application at top level if an error occurs. If the parameter
+ \var{full} is non-zero, any objects on the \slang run time stack
+ will be removed from the stack; otherwise, the stack will be left
+ intact. Any time the stack is believed to be trashed, this routine
+ should be called with a non-zero argument (e.g., if
+ \var{setjmp}/\var{longjmp} is called).
+
+ Calling \var{SLang_restart} does not reset the global variable
+ \var{SLang_Error} to zero. It is up to the application to reset
+ that variable to zero after calling \var{SLang_restart}.
+\example
+#v+
+ while (1)
+ {
+ if (SLang_Error)
+ {
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+ (void) SLang_load_file (NULL);
+ }
+#v-
+\seealso{SLang_init_slang, SLang_load_file}
+\done
+
+
+\function{SLang_byte_compile_file}
+\synopsis{Byte-compile a file for faster loading}
+\usage{int SLang_byte_compile_file(char *fn, int reserved)}
+\description
+ The \var{SLang_byte_compile_file} function ``byte-compiles'' the
+ file \var{fn} for faster loading by the interpreter. This produces
+ a new file whose filename is equivalent to the one specified by
+ \var{fn}, except that a \var{'c'} is appended to the name. For
+ example, if \var{fn} is set to \exmp{init.sl}, then the new file
+ will have the name exmp{init.slc}. The meaning of the second
+ parameter, \var{reserved}, is reserved for future use. For now, set
+ it to \var{0}.
+
+ The function returns zero upon success, or \exmp{-1} upon error and
+ sets SLang_Error accordingly.
+\seealso{SLang_load_file, SLang_init_slang}
+\done
+
+
+\function{SLang_autoload}
+\synopsis{Autoload a function from a file}
+\usage{int SLang_autoload(char *funct, char *filename)}
+\description
+ The \var{SLang_autoload} function may be used to associate a
+ \var{slang} function name \var{funct} with the file \var{filename}
+ such that if \var{funct} has not already been defined when needed,
+ it will be loaded from \var{filename}.
+
+ \var{SLang_autoload} has no effect if \var{funct} has already been
+ defined. Otherwise it declares \var{funct} as a user-defined \slang
+ function. It returns \exmp{0} upon success, or \exmp{-1} upon error.
+\seealso{SLang_load_file, SLang_is_defined}
+\done
+
+
+\function{SLang_load_string}
+\synopsis{Interpret a string}
+\usage{int SLang_load_string(char *str)}
+\description
+ The \var{SLang_load_string} function feeds the string specified by
+ \var{str} to the interpreter for execution. It returns zero upon
+ success, or \exmp{-1} upon failure.
+\seealso{SLang_load_file, SLang_load_object}
+\done
+
+
+\function{SLdo_pop}
+\synopsis{Delete an object from the stack}
+\usage{int SLdo_pop(void)}
+\description
+ This function removes an object from the top of the interpeter's
+ run-time stack and frees any memory associated with it. It returns
+ zero upon success, or \var{-1} upon error (most likely due to a
+ stack-underflow).
+\seealso{SLdo_pop_n, SLang_pop_integer, SLang_pop_string}
+\done
+
+\function{SLdo_pop_n}
+\synopsis{Delete n objects from the stack}
+\usage{int SLdo_pop_n (unsigned int n)}
+\description
+ The \var{SLdo_pop_n} function removes the top \var{n} objects from
+ the interpreter's run-time stack and frees all memory associated
+ with the objects. It returns zero upon success, or \var{-1} upon
+ error (most likely due to a stack-underflow).
+\seealso{SLdo_pop, SLang_pop_integer, SLang_pop_string}
+\done
+
+
+\function{SLang_pop_integer}
+\synopsis{Pop an integer off the stack}
+\usage{int SLang_pop_integer (int *i)}
+\description
+ The \var{SLang_pop_integer} function removes an integer from the
+ top of the interpreter's run-time stack and returns its value via
+ the pointer \var{i}. If successful, it returns zero. However, if
+ the top stack item is not of type \var{SLANG_INT_TYPE}, or the
+ stack is empty, the function will return \exmp{-1} and set
+ \var{SLang_Error} accordingly.
+\seealso{SLang_push_integer, SLang_pop_double}
+\done
+
+
+\function{SLpop_string}
+\synopsis{Pop a string from the stack}
+\usage{int SLpop_string (char **strptr);}
+\description
+ The \var{SLpop_string} function pops a string from the stack and
+ returns it as a malloced pointer. It is up to the calling routine
+ to free this string via a call to \var{free} or \var{SLfree}. If
+ successful, \var{SLpop_string} returns zero. However, if the top
+ stack item is not of type \var{SLANG_STRING_TYPE}, or the stack is
+ empty, the function will return \exmp{-1} and set
+ \var{SLang_Error} accordingly.
+\example
+#v+
+ define print_string (void)
+ {
+ char *s;
+ if (-1 == SLpop_string (&s))
+ return;
+ fputs (s, stdout);
+ SLfree (s);
+ }
+#v-
+\notes
+ This function should not be confused with \var{SLang_pop_slstring},
+ which pops a \em{hashed} string from the stack.
+\seealso{SLang_pop_slstring. SLfree}
+\done
+
+
+\function{SLang_pop_string}
+\synopsis{Pop a string from the stack}
+\usage{int SLang_pop_string(char **strptr, int *do_free)}
+\description
+ The \var{SLpop_string} function pops a string from the stack and
+ returns it as a malloced pointer via \var{strptr}. After the
+ function returns, the integer pointed to by the second parameter
+ will be set to a non-zero value if \var{*strptr} should be freed via
+ \var{free} or \var{SLfree}. If successful, \var{SLpop_string}
+ returns zero. However, if the top stack item is not of type
+ \var{SLANG_STRING_TYPE}, or the stack is empty, the function will
+ return \exmp{-1} and set \var{SLang_Error} accordingly.
+\notes
+ This function is considered obsolete and should not be used by
+ applications. If one requires a malloced string for modification,
+ \var{SLpop_string} should be used. If one requires a constant
+ string that will not be modifed by the application,
+ \var{SLang_pop_slstring} should be used.
+\seealso{SLang_pop_slstring, SLpop_string}
+\done
+
+
+\function{SLang_pop_slstring}
+\synopsis{Pop a hashed string from the stack}
+\usage{int SLang_pop_slstring (char **s_ptr)}
+\description
+ The \var{SLang_pop_slstring} function pops a hashed string from the
+ \slang run-time stack and returns it via \var{s_ptr}. It returns
+ zero if successful, or \-1 upon failure. The resulting string
+ should be freed via a call to \var{SLang_free_slstring} after use.
+\example
+#v+
+ void print_string (void)
+ {
+ char *s;
+ if (-1 == SLang_pop_slstring (&s))
+ return;
+ fprintf (stdout, "%s\n", s);
+ SLang_free_slstring (s);
+ }
+#v-
+\notes
+ \var{SLang_free_slstring} is the preferred function for popping
+ strings. This is a result of the fact that the interpreter uses
+ hashed strings as the native representation for string data.
+
+ One must \em{never} free a hashed string using \var{free} or
+ \var{SLfree}. In addition, one must never make any attempt to
+ modify a hashed string and doing so will result in memory
+ corruption.
+\seealso{SLang_free_slstring, SLpop_string}
+\done
+
+\function{SLang_pop_double}
+\synopsis{Pop a double from the stack}
+\usage{int SLang_pop_double (double *dptr, int *iptr, int *conv)}
+\description
+ The \var{SLang_pop_double} function pops a double precision number
+ from the stack and returns it via \var{dptr}. If the number was
+ derived from an integer, \var{*conv} will be set to \exmp{1} upon
+ return, otherwise, \var{*conv} will be set to \exmp{0}. This
+ function returns \0 upon success, otherwise it returns \-1 and sets
+ \var{SLang_Error} accordingly.
+\notes
+ If one does not care whether or not \exmp{*dptr} was derived from
+ an integer, \var{iptr} and \var{conv} may be passed as \var{NULL}
+ pointers.
+\seealso{SLang_pop_integer, SLang_push_double}
+\done
+
+
+\function{SLang_pop_complex}
+\synopsis{Pop a complex number from the stack}
+\usage{int SLang_pop_complex (double *re, double *im)}
+\description
+ \var{SLang_pop_complex} pops a complex number from the stack and
+ returns it via the parameters \var{re} and \var{im} as the real and
+ imaginary parts of the complex number, respectively. This function
+ automatically converts objects of type \var{SLANG_DOUBLE_TYPE} and
+ \var{SLANG_INT_TYPE} to \var{SLANG_COMPLEX_TYPE}, if necessary.
+ It returns zero upon success, or \-1 upon error setting
+ \var{SLang_Error} accordingly.
+\seealso{SLang_pop_integer, SLang_pop_double, SLang_push_complex}
+\done
+
+
+\function{SLang_push_complex}
+\synopsis{Push a complex number onto the stack}
+\usage{int SLang_push_complex (double re, double im)}
+\description
+ \var{SLang_push_complex} may be used to push the complex number
+ whose real and imaginary parts are given by \var{re} and \var{im},
+ respectively. It returns zero upon success, or \-1 upon error
+ setting \var{SLang_Error} accordingly.
+\seealso{SLang_pop_complex, SLang_push_double}
+\done
+
+
+\function{SLang_push_double}
+\synopsis{Push a double onto the stack}
+\usage{int SLang_push_double(double d)}
+\description
+ \var{SLang_push_double} may be used to push the double precision
+ floating point number \var{d} onto the interpreter's run-time
+ stack. It returns zero upon success, or \-1 upon error setting
+ \var{SLang_Error} accordingly.
+\seealso{SLang_pop_double, SLang_push_integer}
+\done
+
+
+\function{SLang_push_string}
+\synopsis{Push a string onto the stack}
+\usage{int SLang_push_string (char *s)}
+\description
+ \var{SLang_push_string} pushes a copy of the string specified by
+ \var{s} onto the interpreter's run-time stack. It returns zero
+ upon success, or \-1 upon error setting \var{SLang_Error}
+ accordingly.
+\notes
+ If \var{s} is \var{NULL}, this function pushes \var{NULL}
+ (\var{SLANG_NULL_TYPE}) onto the stack.
+\seealso{SLang_push_malloced_string}
+\done
+
+\function{SLang_push_integer}
+\synopsis{Push an integer onto the stack}
+\usage{int SLang_push_integer (int i)}
+\description
+ \var{SLang_push_integer} the integer \var{i} onto the interpreter's
+ run-time stack. It returns zero upon success, or \-1 upon error
+ setting \var{SLang_Error} accordingly.
+\seealso{SLang_pop_integer, SLang_push_double, SLang_push_string}
+\done
+
+\function{SLang_push_malloced_string}
+\synopsis{Push a malloced string onto the stack}
+\usage{int SLang_push_malloced_string (char *s);}
+\description
+ \var{SLang_push_malloced_string} may be used to push a malloced
+ string onto the interpreter's run-time stack. It returns zero upon
+ success, or \-1 upon error setting \var{SLang_Error} accordingly.
+\example
+ The following example illustrates that it is up to the calling
+ routine to free the string if \var{SLang_push_malloced_string} fails:
+#v+
+ int push_hello (void)
+ {
+ char *s = malloc (6);
+ if (s == NULL) return -1;
+ strcpy (s, "hello");
+ if (-1 == SLang_push_malloced_string (s))
+ {
+ free (s);
+ return -1;
+ }
+ return 0;
+ }
+#v-
+\example
+ The function \var{SLang_create_slstring} returns a hashed string.
+ Such a string may not be malloced and should not be passed to
+ \var{SLang_push_malloced_string}.
+\notes
+ If \var{s} is \var{NULL}, this function pushes \var{NULL}
+ (\var{SLANG_NULL_TYPE}) onto the stack.
+\seealso{SLang_push_string, SLmake_string}
+\done
+
+
+\function{SLang_is_defined}
+\synopsis{Check to see if the interpreter defines an object}
+\usage{int SLang_is_defined (char *nm)}
+\description
+ The \var{SLang_is_defined} function may be used to determine
+ whether or not a variable or function whose name is given by
+ \var{em} has been defined. It returns zero if no such object has
+ been defined. Othewise it returns a non-zero value whose meaning
+ is given by the following table:
+#v+
+ 1 intrinsic function (SLANG_INTRINSIC)
+ 2 user-defined slang function (SLANG_FUNCTION)
+ -1 intrinsic variable (SLANG_IVARIABLE)
+ -2 user-defined global variable (SLANG_GVARIABLE)
+#v-
+\seealso{SLadd_intrinsic_function, SLang_run_hooks, SLang_execute_function}
+\done
+
+
+\function{SLang_run_hooks}
+\synopsis{Run a user-defined hook with arguments}
+\usage{int SLang_run_hooks (char *fname, unsigned int n, ...)}
+\description
+ The \var{SLang_run_hooks} function may be used to execute a
+ user-defined function named \var{fname}. Before execution of the
+ function, the \var{n} string arguments specified by the variable
+ parameter list are pushed onto the stack. If the function
+ \var{fname} does not exist, \var{SLang_run_hooks} returns zero;
+ otherwise, it returns \exmp{1} upon successful execution of the
+ function, or \-1 if an error occurred.
+\example
+ The \jed editor uses \var{SLang_run_hooks} to setup the mode of a
+ buffer based on the filename extension of the file associated with
+ the buffer:
+#v+
+ char *ext = get_filename_extension (filename);
+ if (ext == NULL) return -1;
+ if (-1 == SLang_run_hooks ("mode_hook", 1, ext))
+ return -1;
+ return 0;
+#v-
+\seealso{SLang_is_defined, SLang_execute_function}
+\done
+
+
+\function{SLang_execute_function}
+\synopsis{Execute a user or intrinsic function}
+\usage{int SLang_execute_function (char *fname)}
+\description
+ This function may be used to execute either a user-defined function
+ or an intrinisic function. The name of the function is specified
+ by \var{fname}. It returns zero if \var{fname} is not defined, or
+ \exmp{1} if the function was successfully executed, or \-1 upon
+ error.
+\notes
+ The function \var{SLexecute_function} may be a better alternative
+ for some uses.
+\seealso{SLang_run_hooks, SLexecute_function, SLang_is_defined}
+\done
+
+\function{SLang_verror}
+\synopsis{Signal an error with a message}
+\usage{void SLang_verror (int code, char *fmt, ...);}
+\description
+ The \var{SLang_verror} function sets \var{SLang_Error} to
+ \var{code} if \var{SLang_Error} is 0. It also displays the error
+ message implied by the \var{printf} variable argument list using
+ \var{fmt} as the format.
+\example
+#v+
+ FILE *open_file (char *file)
+ {
+ char *file = "my_file.dat";
+ if (NULL == (fp = fopen (file, "w")))
+ SLang_verror (SL_INTRINSIC_ERROR, "Unable to open %s", file);
+ return fp;
+ }
+#v-
+\seealso{SLang_vmessage, SLang_exit_error}
+\done
+
+
+\function{SLang_doerror}
+\synopsis{Signal an error}
+\usage{void SLang_doerror (char *err_str)}
+\description
+ The \var{SLang_doerror} function displays the string \var{err_str}
+ to the error device and signals a \slang error.
+\notes
+ \var{SLang_doerror} is considered to obsolete. Applications should
+ use the \var{SLang_verror} function instead.
+\seealso{SLang_verror, SLang_exit_error}
+\done
+
+
+\function{SLang_get_function}
+\synopsis{Get a pointer to a \slang function}
+\usage{SLang_Name_Type *SLang_get_function (char *fname)}
+\description
+ This function returns a pointer to the internal \slang table entry
+ of a function whose name is given by \var{fname}. It returns
+ \var{NULL} upon failure. The value returned by this function can be
+ used \var{SLexecute_function} to call the function directly
+ from C.
+\seealso{SLexecute_function}
+\done
+
+
+
+\function{SLexecute_function}
+\synopsis{Execute a \slang or intrinsic function}
+\usage{int SLexecute_function (SLang_Name_Type *nt)}
+\description
+ The \var{SLexecute_function} allows an application to call the
+ \slang function specified by the \var{SLang_Name_Type} pointer
+ \var{nt}. This parameter must be non \var{NULL} and must have been
+ previously obtained by a call to \var{SLang_get_function}.
+\example
+ Consider the \slang function:
+#v+
+ define my_fun (x)
+ {
+ return x^2 - 2;
+ }
+#v-
+ Suppose that it is desired to call this function many times with
+ different values of x. There are at least two ways to do this.
+ The easiest way is to use \var{SLang_execute_function} by passing
+ the string \exmp{"my_fun"}. A better way that is much faster is to
+ use \var{SLexecute_function}:
+#v+
+ int sum_a_function (char *fname, double *result)
+ {
+ double sum, x, y;
+ SLang_Name_Type *nt;
+
+ if (NULL == (nt = SLang_get_function (fname)))
+ return -1;
+
+ sum = 0;
+ for (x = 0; x < 10.0; x += 0.1)
+ {
+ SLang_start_arg_list ();
+ if (-1 == SLang_push_double (x))
+ return -1;
+ SLang_end_arg_list ();
+ if (-1 == SLexecute_function (nt))
+ return -1;
+ if (-1 == SLang_pop_double (&y, NULL, NULL))
+ return -1;
+
+ sum += y;
+ }
+ return sum;
+ }
+#v-
+ Although not necessary in this case, \var{SLang_start_arg_list} and
+ \var{SLang_end_arg_list} were used to provide the function with
+ information about the number of parameters passed to it.
+\seealso{SLang_get_function, SLang_start_arg_list, SLang_end_arg_list}
+\done
+
+
+\function{SLang_peek_at_stack}
+\synopsis{Find the type of object on the top of the stack}
+\usage{int SLang_peek_at_stack (void)}
+\description
+ The \var{SLang_peek_at_stack} function is useful for determining the
+ data type of the object at the top of the stack. It returns the
+ data type, or -1 upon a stack-underflow error. It does not remove
+ anything from the stack.
+\seealso{SLang_pop_string, SLang_pop_integer}
+\done
+
+
+\function{SLmake_string}
+\synopsis{Duplicate a string}
+\usage{char *SLmake_string (char *s)}
+\description
+ The \var{SLmake_string} function creates a new copy of the string
+ \var{s}, via \var{malloc}, and returns it. Upon failure it returns
+ \var{NULL}. Since the resulting string is malloced, it should be
+ freed when nolonger needed via a call to either \var{free} or
+ \var{SLfree}.
+\notes
+ \var{SLmake_string} should not be confused with the function
+ \var{SLang_create_slstring}, which performs a similar function.
+\seealso{SLmake_nstring, SLfree, SLmalloc, SLang_create_slstring}
+\done
+
+
+\function{SLmake_nstring}
+\synopsis{Duplicate a substring}
+\usage{char *SLmake_nstring (char *s, unsigned int n)}
+\description
+ This function is like \var{SLmake_nstring} except that it creates a
+ null terminated string formed from the first \var{n} characters of
+ \var{s}. Upon failure, it returns \var{NULL}, otherwise it returns
+ the new string. When nolonger needed, the returned string should be
+ freed with either \var{free} or \var{SLfree}.
+\seealso{SLmake_nstring, SLfree, SLang_create_nslstring}
+\done
+
+
+\function{SLang_create_nslstring}
+\synopsis{Created a hashed substring}
+\usage{char *SLang_create_nslstring (char *s, unsigned int n)}
+\description
+ \var{SLang_create_nslstring} is like \var{SLang_create_slstring}
+ except that only the first \var{n} characters of \var{s} are used to
+ perform the string. Upon error, it returns \var{NULL}, otherwise it
+ returns the hashed substring. Such a string must be freed by the
+ function \var{SLang_free_slstring}.
+\notes
+ Do not use \var{free} or \var{SLfree} to free the string returned by
+ \var{SLang_create_slstring} or \var{SLang_create_nslstring}. Also
+ it is important that no attempt is made to modify the hashed string
+ returned by either of these functions. If one needs to modify a
+ string, the functions \var{SLmake_string} or \var{SLmake_nstring}
+ should be used instead.
+\seealso{SLang_free_slstring, SLang_create_slstring, SLmake_nstring}
+\done
+
+\function{SLang_create_slstring}
+\synopsis{Create a hashed string}
+\usage{char *SLang_create_slstring (char *s)}
+\description
+ The \var{SLang_create_slstring} creates a copy of \var{s} and
+ returns it as a hashed string. Upon error, the function returns
+ \var{NULL}, otherwise it returns the hashed string. Such a string
+ must only be freed via the \var{SLang_free_slstring} function.
+\notes
+ Do not use \var{free} or \var{SLfree} to free the string returned by
+ \var{SLang_create_slstring} or \var{SLang_create_nslstring}. Also
+ it is important that no attempt is made to modify the hashed string
+ returned by either of these functions. If one needs to modify a
+ string, the functions \var{SLmake_string} or \var{SLmake_nstring}
+ should be used instead.
+\seealso{SLang_free_slstring, SLang_create_nslstring, SLmake_string}
+\done
+
+
+\function{SLang_free_slstring}
+\synopsis{Free a hashed string}
+\usage{void SLang_free_slstring (char *s)}
+\description
+ The \var{SLang_free_slstring} function is used to free a hashed
+ string such as one returned by \var{SLang_create_slstring},
+ \var{SLang_create_nslstring}, or \var{SLang_create_static_slstring}.
+ If \var{s} is \var{NULL}, the routine does nothing.
+\seealso{SLang_create_slstring, SLang_create_nslstring, SLang_create_static_slstring}
+\done
+
+
+\function{SLang_concat_slstrings}
+\synopsis{Concatenate two strings to produce a hashed string}
+\usage{char *SLang_concat_slstrings (char *a, char *b)}
+\description
+ The \var{SLang_concat_slstrings} function concatenates two strings,
+ \var{a} and \var{b}, and returns the result as a hashed string.
+ Upon failure, \var{NULL} is returned.
+\notes
+ A hashed string can only be freed using \var{SLang_free_slstring}.
+ Never use either \var{free} or \var{SLfree} to free a hashed string,
+ otherwise memory corruption will result.
+\seealso{SLang_free_slstring, SLang_create_slstring}
+\done
+
+\function{SLang_create_static_slstring}
+\synopsis{Create a hashed string}
+\usage{char *SLang_create_static_slstring (char *s_literal)}
+\description
+ The \var{SLang_create_static_slstring} creates a hashed string from
+ the string literal \var{s_literal} and returns the result. Upon
+ failure it returns \var{NULL}.
+\example
+#v+
+ char *create_hello (void)
+ {
+ return SLang_create_static_slstring ("hello");
+ }
+#v-
+\notes
+ This function should only be used with string literals.
+\seealso{SLang_create_slstring, SLang_create_nslstring}
+\done
+
+
+\function{SLmalloc}
+\synopsis{Allocate some memory}
+\usage{char *SLmalloc (unsigned int nbytes)}
+\description
+ This function uses \var{malloc} to allocate \var{nbytes} of memory.
+ Upon error it returns \var{NULL}; otherwise it returns a pointer to
+ the allocated memory. One should use \var{SLfree} to free the
+ memory after used.
+\seealso{SLfree, SLrealloc, SLcalloc}
+\done
+
+
+\function{SLcalloc}
+\synopsis{Allocate some memory}
+\usage{char *SLcalloc (unsigned int num_elem, unsigned int elem_size)}
+\description
+ This function uses \var{calloc} to allocate memory for
+ \var{num_elem} objects with each of size \var{elem_size} and returns
+ the result. In addition, the newly allocated memory is zeroed.
+ Upon error it returns \var{NULL}; otherwise it returns a pointer to
+ the allocated memory. One should use \var{SLfree} to free the
+ memory after used.
+\seealso{SLmalloc, SLrealloc, SLfree}
+\done
+
+
+\function{SLfree}
+\synopsis{Free some allocated memory}
+\usage{void SLfree (char *ptr)}
+\description
+ The \var{SLfree} function uses \var{free} to deallocate the memory
+ specified by \var{ptr}, which may be \var{NULL} in which case the
+ function does nothing.
+\notes
+ Never use this function to free a hashed string returned by one of
+ the family of \var{slstring} functions, e.g.,
+ \var{SLang_pop_slstring}.
+\seealso{SLmalloc, SLcalloc, SLrealloc, SLmake_string}
+\done
+
+
+\function{SLrealloc}
+\synopsis{Resize a dynamic memory block}
+\usage{char *SLrealloc (char *ptr, unsigned int new_size)}
+\description
+ The \var{SLrealloc} uses the \var{realloc} function to resize the
+ memory block specified by \var{ptr} to the new size \var{new_size}.
+ If \var{ptr} is \var{NULL}, the function call is equivalent to
+ \exmp{SLmalloc(new_size)}. Similarly, if \var{new_size} is zero,
+ the function call is equivalent to \var{SLfree(ptr)}.
+
+ If the function fails, or if \var{new_size} is zero, \var{NULL} is
+ returned. Otherwise a pointer is returned to the (possibly moved)
+ new block of memory.
+\seealso{SLfree, SLmalloc, SLcalloc}
+\done
+
+
+\function{SLcurrent_time_string}
+\synopsis{Get the current time as a string}
+\usage{char *SLcurrent_time_string (void)}
+\description
+ The \var{SLcurrent_time_string} function uses the C library function
+ \var{ctime} to obtain a string representation of the
+ current date and time in the form
+#v+
+ "Wed Dec 10 12:50:28 1997"
+#v-
+ However, unlike the \var{ctime} function, a newline character is not
+ present in the string.
+
+ The returned value points to a statically allocated memory block
+ which may get overwritten on subsequent function calls.
+\seealso{SLmake_string}
+\done
+
+
+
+\function{SLatoi}
+\synopsis{Convert a text string to an integer}
+\usage{int SLatoi(unsigned char *str}
+\description
+ \var{SLatoi} parses the string \var{str} to interpret it as an
+ integer value. Unlike \var{atoi}, \var{SLatoi} can also parse
+ strings containing integers expressed in
+ hexidecimal (e.g., \exmp{"0x7F"}) and octal (e.g., \exmp{"012"}.)
+ notation.
+\seealso{SLang_guess_type}
+\done
+
+
+\function{SLang_pop_fileptr}
+\synopsis{Pop a file pointer}
+\usage{int SLang_pop_fileptr (SLang_MMT_Type **mmt, FILE **fp)}
+\description
+ \var{SLang_pop_fileptr} pops a file pointer from the \slang
+ run-time stack. It returns zero upon success, or \-1 upon failure.
+
+ A \slang file pointer (SLANG_FILEPTR_TYPE) is actually a memory
+ managed object. For this reason, \var{SLang_pop_fileptr} also
+ returns the memory managed object via the argument list. It is up
+ to the calling routine to call \var{SLang_free_mmt} to free the
+ object.
+\example
+ The following example illustrates an application defined intrinsic
+ function that writes a user defined double precision number to a
+ file. Note the use of \var{SLang_free_mmt}:
+#v+
+ int write_double (void)
+ {
+ double t;
+ SLang_MMT_Type *mmt;
+ FILE *fp;
+ int status;
+
+ if (-1 == SLang_pop_double (&d, NULL, NULL))
+ return -1;
+ if (-1 == SLang_pop_fileptr (&mmt, &fp))
+ return -1;
+
+ status = fwrite (&d, sizeof (double), 1, fp);
+ SLang_free_mmt (mmt);
+ return status;
+ }
+#v-
+ This function can be used by a \slang function as follows:
+#v+
+ define write_some_values ()
+ {
+ variable fp, d;
+
+ fp = fopen ("myfile.dat", "wb");
+ if (fp == NULL)
+ error ("file failed to open");
+ for (d = 0; d < 10.0; d += 0.1)
+ {
+ if (-1 == write_double (fp, d))
+ error ("write failed");
+ }
+ if (-1 == fclose (fp))
+ error ("fclose failed");
+ }
+#v-
+\seealso{SLang_free_mmt, SLang_pop_double}
+\done
+
+
+\function{SLadd_intrinsic_function}
+\synopsis{Add a new intrinsic function to the interpreter}
+\usage{int SLadd_intrinsic_function (name, f, type, nargs, ...)}
+#v+
+ char *name
+ FVOID_STAR f
+ unsigned char type
+ unsigned int nargs
+#v-
+\description
+ The \var{SLadd_intrinsic_function} function may be used to add a new
+ intrinsic function. The \slang name of the function is specified by
+ \var{name} and the actual function pointer is given by \var{f}, cast
+ to \var{FVOID_STAR}. The third parameter, \var{type} specifies the
+ return type of the function and must be one of the following values:
+#v+
+ SLANG_VOID_TYPE (returns nothing)
+ SLANG_INT_TYPE (returns int)
+ SLANG_DOUBLE_TYPE (returns double)
+ SLANG_STRING_TYPE (returns char *)
+#v-
+ The \var{nargs} parameter specifies the number of parameters to pass
+ to the function. The variable argument list following \var{nargs}
+ must consists of \var{nargs} integers which specify the data type of
+ each argument.
+
+ The function returns zero upon success or \-1 upon failure.
+\example
+ The \jed editor uses this function to change the \var{system}
+ intrinsic function to the following:
+#v+
+ static int jed_system (char *cmd)
+ {
+ if (Jed_Secure_Mode)
+ {
+ msg_error ("Access denied.");
+ return -1;
+ }
+ return SLsystem (cmd);
+ }
+#v-
+ After initializing the interpreter with \var{SLang_init_slang},
+ \jed calls \var{SLadd_intrinsic_function} to substitute the above
+ definition for the default \slang definition:
+#v+
+ if (-1 == SLadd_intrinsic_function ("system", (FVOID_STAR)jed_system,
+ SLANG_INT_TYPE, 1,
+ SLANG_STRING_TYPE))
+ return -1;
+#v-
+\seealso{SLadd_intrinsic_variable, SLadd_intrinsic_array}
+\done
+
+\function{SLadd_intrinsic_variable}
+\synopsis{Add an intrinsic variable to the interpreter}
+\usage{int SLadd_intrinsic_variable (name, addr, type, rdonly)}
+#v+
+ char *name
+ VOID_STAR type
+ unsigned char type
+ int rdonly
+#v-
+\description
+ The \var{SLadd_intrinsic_variable} function adds an intrinsic
+ variable called \var{name} to the interpeter. The second parameter
+ \var{addr} specifies the address of the variable (cast to
+ \var{VOID_STAR}). The third parameter, \var{type}, specifies the
+ data type of the variable. If the fourth parameter, \var{rdonly},
+ is non-zero, the variable will interpreted by the interpreter as
+ read-only.
+
+ If successful, \var{SLadd_intrinsic_variable} returns zero,
+ otherwise it returns \-1.
+\example
+ Suppose that \var{My_Global_Int} is a global variable (at least not
+ a local one):
+#v+
+ int My_Global_Int;
+#v-
+ It can be added to the interpreter via the function call
+#v+
+ if (-1 == SLadd_intrinsic_variable ("MyGlobalInt",
+ (VOID_STAR)&My_Global_Int,
+ SLANG_INT_TYPE, 0))
+ exit (1);
+#v-
+\notes
+ The current implementation requires all pointer type intrinsic
+ variables to be read-only. For example,
+#v+
+ char *My_Global_String;
+#v-
+ is of type \var{SLANG_STRING_TYPE}, and must be declared as
+ read-only. Finally, not that
+#v+
+ char My_Global_Char_Buf[256];
+#v-
+ is \em{not} a \var{SLANG_STRING_TYPE} object. This difference is
+ very important because internally the interpreter dereferences the
+ address passed to it to get to the value of the variable.
+\seealso{SLadd_intrinsic_function, SLadd_intrinsic_array}
+\done
+}
+
+
+\function{SLclass_add_unary_op}
+\synopsis{??}
+\usage{int SLclass_add_unary_op (unsigned char,int (*) (int, unsigned char, VOID_STAR, unsigned int, VOID_STAR), int (*) (int, unsigned char, unsigned char *));}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{SLclass_add_app_unary_op}
+\synopsis{??}
+\usage{int SLclass_add_app_unary_op (unsigned char, int (*) (int,unsigned char, VOID_STAR, unsigned int,VOID_STAR),int (*) (int, unsigned char, unsigned char *));}
+\description
+??
+\seealso{??}
+\done
+
+\function{SLclass_add_binary_op}
+\synopsis{??}
+\usage{int SLclass_add_binary_op (unsigned char, unsigned char,int (*)(int, unsigned char, VOID_STAR, unsigned int,unsigned char, VOID_STAR, unsigned int,VOID_STAR),int (*) (int, unsigned char, unsigned char, unsigned char *));}
+\description
+??
+\seealso{??}
+\done
+
+\function{SLclass_add_math_op}
+\synopsis{??}
+\usage{int SLclass_add_math_op (unsigned char,int (*)(int,unsigned char, VOID_STAR, unsigned int,VOID_STAR),int (*)(int, unsigned char, unsigned char *));}
+\description
+??
+\seealso{??}
+\done
+
+\function{SLclass_add_typecast}
+\synopsis{??}
+\usage{int SLclass_add_typecast (unsigned char, unsigned char int (*)_PROTO((unsigned char, VOID_STAR, unsigned int,unsigned char, VOID_STAR)),int);}
+\description
+??
+\seealso{??}
+\done
+
+\function{SLang_init_tty}
+\synopsis{Initialize the terminal keyboard interface}
+\usage{int SLang_init_tty (int intr_ch, int no_flow_ctrl, int opost)}
+\description
+ \var{SLang_init_tty} initializes the terminal for single character
+ input. If the first parameter \var{intr_ch} is in the range 0-255,
+ it will be used as the interrupt character, e.g., under Unix this
+ character will generate a \var{SIGINT} signal. Otherwise, if it is
+ \exmp{-1}, the interrupt character will be left unchanged.
+
+ If the second parameter \var{no_flow_ctrl} is non-zero, flow control
+ (\var{XON}/\var{XOFF}) processing will be
+ enabled.
+
+ If the last parmeter \var{opost} is non-zero, output processing by the
+ terminal will be enabled. If one intends to use this function in
+ conjunction with the \slang screen management routines
+ (\var{SLsmg}), this paramete shold be set to zero.
+
+ \var{SLang_init_tty} returns zero upon success, or \-1 upon error.
+\notes
+ Terminal I/O is a complex subject. The \slang interface presents a
+ simplification that the author has found useful in practice. For
+ example, the only special character processing that
+ \var{SLang_init_tty} enables is that of the \var{SIGINT} character,
+ and the generation of other signals via the keyboard is disabled.
+ However, generation of the job control signal \var{SIGTSTP} is possible
+ via the \var{SLtty_set_suspend_state} function.
+
+ Under Unix, the integer variable \var{SLang_TT_Read_FD} is used to
+ specify the input descriptor for the terminal. If
+ \var{SLang_TT_Read_FD} represents a terminal device as determined
+ via the \var{isatty} system call, then it will be used as the
+ terminal file descriptor. Otherwise, the terminal device
+ \exmp{/dev/tty} will used as the input device. The default value of
+ \var{SLang_TT_Read_FD} is \-1 which causes \exmp{/dev/tty} to be
+ used. So, if you prefer to use \var{stdin} for input, then set
+ \var{SLang_TT_Read_FD} to \exmp{fileno(stdin)} \em{before} calling
+ \var{SLang_init_tty}.
+
+ If the variable \var{SLang_TT_Baud_Rate} is zero when this function
+ is called, the function will attempt to determine the baud rate by
+ querying the terminal driver and set \var{SLang_TT_Baud_Rate} to
+ that value.
+\seealso{SLang_reset_tty, SLang_getkey, SLtty_set_suspend_state}
+\done
+
+
+\function{SLang_reset_tty}
+\synopsis{Reset the terminal}
+\usage{void SLang_reset_tty (void)}
+\description
+ \var{SLang_reset_tty} resets the terminal interface back to the
+ state it was in before \var{SLang_init_tty} was called.
+\seealso{SLang_init_tty}
+\done
+
+
+\function{SLtty_set_suspend_state}
+\synopsis{Enable or disable keyboard suspension}
+\usage{void SLtty_set_suspend_state (int s)}
+\description
+ The \var{SLtty_set_suspend_state} function may be used to enable or
+ disable keyboard generation of the \var{SIGTSTP} job control signal.
+ If \var{s} is non-zero, generation of this signal via the terminal
+ interface will be enabled, otherwise it will be disabled.
+
+ This function should only be called after the terminal driver has be
+ initialized via \var{SLang_init_tty}. The \var{SLang_init_tty}
+ always disables the generation of \var{SIGTSTP} via the keyboard.
+\seealso{SLang_init_tty}
+\done
+
+\function{SLang_getkey}
+\synopsis{Read a character from the keyboard}
+\usage{unsigned int SLang_getkey (void);}
+\description
+ The \var{SLang_getkey} reads a single character from the terminal
+ and returns it. The terminal must first be initialized via a call
+ to \var{SLang_init_tty} before this function can be called. Upon
+ success, \var{SLang_getkey} returns the character read from the
+ terminal, otherwise it returns \var{SLANG_GETKEY_ERROR}.
+\seealso{SLang_init_tty, SLang_input_pending, SLang_ungetkey}
+\done
+
+\function{SLang_ungetkey_string}
+\synopsis{Unget a key string}
+\usage{int SLang_ungetkey_string (unsigned char *buf, unsigned int n)}
+\description
+ The \var{SLang_ungetkey_string} function may be used to push the
+ \var{n} characters pointed to by \var{buf} onto the buffered input
+ stream that \var{SLgetkey} uses. If there is not enough room for
+ the characters, \-1 is returned and none are buffered. Otherwise,
+ it returns zero.
+\notes
+ The difference between \var{SLang_buffer_keystring} and
+ \var{SLang_ungetkey_string} is that the \var{SLang_buffer_keystring}
+ appends the characters to the end of the getkey buffer, whereas
+ \var{SLang_ungetkey_string} inserts the characters at the beginning
+ of the input buffer.
+\seealso{SLang_ungetkey, SLang_getkey}
+\done
+
+
+\function{SLang_buffer_keystring}
+\synopsis{Append a keystring to the input buffer}
+\usage{int SLang_buffer_keystring (unsigned char *b, unsigned int len)}
+\description
+ \var{SLang_buffer_keystring} places the \var{len} characters
+ specified by \var{b} at the \em{end} of the buffer that
+ \var{SLang_getkey} uses. Upon success it returns 0; otherwise, no
+ characters are buffered and it returns \-1.
+\notes
+ The difference between \var{SLang_buffer_keystring} and
+ \var{SLang_ungetkey_string} is that the \var{SLang_buffer_keystring}
+ appends the characters to the end of the getkey buffer, whereas
+ \var{SLang_ungetkey_string} inserts the characters at the beginning
+ of the input buffer.
+\seealso{SLang_getkey, SLang_ungetkey, SLang_ungetkey_string}
+\done
+
+
+\function{SLang_ungetkey}
+\synopsis{Push a character back onto the input buffer}
+\usage{int SLang_ungetkey (unsigned char ch)}
+\description
+ \var{SLang_ungetkey} pushes the character \var{ch} back onto the
+ \var{SLgetkey} input stream. Upon success, it returns zero,
+ otherwise it returns \1.
+\example
+ This function is implemented as:
+#v+
+ int SLang_ungetkey (unsigned char ch)
+ {
+ return SLang_ungetkey_string(&ch, 1);
+ }
+#v-
+\seealso{SLang_getkey, SLang_ungetkey_string}
+\done
+
+
+\function{SLang_flush_input}
+\synopsis{Discard all keyboard input waiting to be read}
+\usage{void SLang_flush_input (void)}
+\description
+ \var{SLang_flush_input} discards all input characters waiting to be
+ read by the \var{SLang_getkey} function.
+\seealso{SLang_getkey}
+\done
+
+
+\function{SLang_input_pending}
+\synopsis{Check to see if input is pending}
+\usage{int SLang_input_pending (int tsecs)}
+\description
+ \var{SLang_input_pending} may be used to see if an input character
+ is available to be read without causing \var{SLang_getkey} to block.
+ It will wait up to \var{tsecs} tenths of a second if no characters
+ are immediately available for reading. If \var{tsecs} is less than
+ zero, then \var{SLang_input_pending} will wait \exmp{-tsecs}
+ milliseconds for input, otherwise \var{tsecs} represents \var{1/10}
+ of a second intervals.
+\notes
+ Not all systems support millisecond resolution.
+\seealso{SLang_getkey}
+\done
+
+
+\function{SLang_set_abort_signal}
+\synopsis{Set the signal to trap SIGINT}
+\usage{void SLang_set_abort_signal (void (*f)(int));}
+\description
+ \var{SLang_set_abort_signal} sets the function that gets
+ triggered when the user presses the interrupt key (\var{SIGINT}) to
+ the function \var{f}. If \var{f} is \var{NULL} the default handler
+ will get installed.
+\example
+ The default interrupt handler on a Unix system is:
+#v+
+ static void default_sigint (int sig)
+ {
+ SLKeyBoard_Quit = 1;
+ if (SLang_Ignore_User_Abort == 0) SLang_Error = SL_USER_BREAK;
+ SLsignal_intr (SIGINT, default_sigint);
+ }
+#v-
+\notes
+ For Unix programmers, the name of this function may appear
+ misleading since it is associated with \var{SIGINT} and not
+ \var{SIGABRT}. The origin of the name stems from the original intent
+ of the function: to allow the user to abort the running of a \slang
+ interpreter function.
+\seealso{SLang_init_tty, SLsignal_intr}
+\done
+
+
+\function{SLkm_define_key}
+\synopsis{Define a key in a keymap}
+\usage{int SLkm_define_key (char *seq, FVOID_STAR f, SLKeyMap_List_Type *km)}
+\description
+ \var{SLkm_define_key} associates the key sequence \var{seq} with the
+ function pointer \var{f} in the keymap specified by \var{km}. Upon
+ success, it returns zero, otherwise it returns a negative integer
+ upon error.
+\seealso{SLkm_define_keysym, SLang_define_key}
+\done
+
+
+
+\function{SLang_define_key}
+\synopsis{Define a key in a keymap}
+\usage{int SLang_define_key(char *seq, char *fun, SLKeyMap_List_Type *km)}
+\description
+ \var{SLang_define_key} associates the key sequence \var{seq} with
+ the function whose name is \var{fun} in the keymap specified by
+ \var{km}.
+\seealso{SLkm_define_keysym, SLkm_define_key}
+\done
+
+
+\function{SLkm_define_keysym}
+\synopsis{Define a keysym in a keymap}
+\usage{int SLkm_define_keysym (seq, ks, km)}
+#v+
+ char *seq;
+ unsigned int ks;
+ SLKeyMap_List_Type *km;
+#v-
+\description
+ \var{SLkm_define_keysym} associates the key sequence \var{seq} with
+ the keysym \var{ks} in the keymap \var{km}. Keysyms whose value is
+ less than or equal to \exmp{0x1000} is reserved by the library and
+ should not be used.
+\seealso{SLkm_define_key, SLang_define_key}
+\done
+
+\function{SLang_undefine_key}
+\synopsis{Undefined a key from a keymap}
+\usage{void SLang_undefine_key(char *seq, SLKeyMap_List_Type *km);}
+\description
+ \var{SLang_undefine_key} removes the key sequence \var{seq} from the
+ keymap \var{km}.
+\seealso{SLang_define_key}
+\done
+
+\function{SLang_create_keymap}
+\synopsis{Create a new keymap}
+\usage{SLKeyMap_List_Type *SLang_create_keymap (name, km)}
+#v+
+ char *name;
+ SLKeyMap_List_Type *km;
+#v-
+\description
+ \var{SLang_create_keymap} creates a new keymap called \var{name} by
+ copying the key definitions from the keymap \var{km}. If \var{km}
+ is \var{NULL}, the newly created keymap will be empty and it is up
+ to the calling routine to initialize it via the
+ \var{SLang_define_key} and \var{SLkm_define_keysym} functions.
+ \var{SLang_create_keymap} returns a pointer to the new keymap, or
+ \var{NULL} upon failure.
+\seealso{SLang_define_key, SLkm_define_keysym}
+\done
+
+
+\function{SLang_do_key}
+\synopsis{Read a keysequence and return its keymap entry}
+\usage{SLang_Key_Type *SLang_do_key (kml, getkey)}
+#v+
+ SLKeyMap_List_Type *kml;
+ int (*getkey)(void);
+#v-
+\description
+ The \var{SLang_do_key} function reads characters using the function
+ specified by the \var{getkey} function pointer and uses the
+ key sequence to return the appropriate entry in the keymap specified
+ by \var{kml}.
+
+ \var{SLang_do_key} returns \var{NULL} if the key sequence is not
+ defined by the keymap, otherwise it returns a pointer to an object
+ of type \var{SLang_Key_Type}, which is defined in \exmp{slang.h} as
+#v+
+ #define SLANG_MAX_KEYMAP_KEY_SEQ 14
+ typedef struct SLang_Key_Type
+ {
+ struct SLang_Key_Type *next;
+ union
+ {
+ char *s;
+ FVOID_STAR f;
+ unsigned int keysym;
+ }
+ f;
+ unsigned char type; /* type of function */
+ #define SLKEY_F_INTERPRET 0x01
+ #define SLKEY_F_INTRINSIC 0x02
+ #define SLKEY_F_KEYSYM 0x03
+ unsigned char str[SLANG_MAX_KEYMAP_KEY_SEQ + 1];/* key sequence */
+ }
+SLang_Key_Type;
+
+#v-
+ The \var{type} field specifies which field of the union \var{f}
+ should be used. If \var{type} is \var{SLKEY_F_INTERPRET}, then
+ \var{f.s} is a string that should be passed to the interpreter for
+ evaluation. If \var{type} is \var{SLKEY_F_INTRINSIC}, then
+ \var{f.f} refers to function that should be called. Otherwise,
+ \var{type} is \var{SLKEY_F_KEYSYM} and \var{f.keysym} represents the
+ value of the keysym that is associated with the key sequence.
+\seealso{SLkm_define_keysym, SLkm_define_key}
+\done
+
+
+\function{SLang_find_key_function}
+\synopsis{Obtain a function pointer associated with a keymap}
+\usage{FVOID_STAR SLang_find_key_function (fname, km);}
+#v+
+ char *fname;
+ SLKeyMap_List_Type *km;
+#v-
+\description
+ The \var{SLang_find_key_function} routine searches through the
+ \var{SLKeymap_Function_Type} list of functions associated with the
+ keymap \var{km} for the function with name \var{fname}.
+ If a matching function is found, a pointer to the function will
+ be returned, otherwise \var{SLang_find_key_function} will return
+ \var{NULL}.
+\seealso{SLang_create_keymap, SLang_find_keymap}
+\done
+
+
+\function{SLang_find_keymap}
+\synopsis{Find a keymap}
+\usage{SLKeyMap_List_Type *SLang_find_keymap (char *keymap_name);}
+\description
+ The \var{SLang_find_keymap} function searches through the list of
+ keymaps looking for one whose name is \var{keymap_name}. If a
+ matching keymap is found, the function returns a pointer to the
+ keymap. It returns \var{NULL} if no such keymap exists.
+\seealso{SLang_create_keymap, SLang_find_key_function}
+\done
+
+\function{SLang_process_keystring}
+\synopsis{Un-escape a key-sequence}
+\usage{char *SLang_process_keystring (char *kseq);}
+\description
+ The \var{SLang_process_keystring} function converts an escaped key
+ sequence to its raw form by converting two-character combinations
+ such as \var{^A} to the \em{single} character \exmp{Ctrl-A} (ASCII
+ 1). In addition, if the key sequence contains constructs such as
+ \exmp{^(XX)}, where \exmp{XX} represents a two-character termcap
+ specifier, the termcap escape sequence will be looked up and
+ substituted.
+
+ Upon success, \var{SLang_process_keystring} returns a raw
+ key-sequence whose first character represents the total length of
+ the key-sequence, including the length specifier itself. It returns
+ \var{NULL} upon failure.
+\example
+ Consider the following examples:
+#v+
+ SLang_process_keystring ("^X^C");
+ SLang_process_keystring ("^[[A");
+#v-
+ The first example will return a pointer to a buffer of three characters
+ whose ASCII values are given by \exmp{\{3,24,3\}}. Similarly, the
+ second example will return a pointer to the four characters
+ \exmp{\{4,27,91,65\}}. Finally, the result of
+#v+
+ SLang_process_keystring ("^[^(ku)");
+#v-
+ will depend upon the termcap/terminfo capability \exmp{"ku"}, which
+ represents the escape sequence associated with the terminal's UP
+ arrow key. For an ANSI terminal whose UP arrow produces
+ \exmp{"ESC [ A"}, the result will be \exmp{5,27,27,91,65}.
+\notes
+ \var{SLang_process_keystring} returns a pointer to a static area
+ that will be overwritten on subsequent calls.
+\seealso{SLang_define_key, SLang_make_keystring}
+\done
+
+\function{SLang_make_keystring}
+\synopsis{Make a printable key sequence}
+\usage{char *SLang_make_keystring (unsigned char *ks);}
+\description
+ The \var{SLang_make_keystring} function takes a raw key sequence
+ \var{ks} and converts it to a printable form by converting
+ characters such as ASCII 1 (ctrl-A) to \exmp{^A}. That is, it
+ performs the opposite function of \var{SLang_process_keystring}.
+\notes
+ This function returns a pointer to a static area that will be
+ overwritten on the next call to \var{SLang_make_keystring}.
+\seealso{SLang_process_keystring}
+\done
+
+
+\function{SLextract_list_element}
+\synopsis{Extract a substring of a delimited string}
+\usage{int SLextract_list_element (dlist, nth, delim, buf, buflen)}
+#v+
+ char *dlist;
+ unsigned int nth;
+ char delim;
+ char *buf;
+ unsigned int buflen;
+#v-
+\description
+ \var{SLextract_list_element} may be used to obtain the \var{nth}
+ element of a list of strings, \var{dlist}, that are delimited by the
+ character \var{delim}. The routine copies the \var{nth} element of
+ \var{dlist} to the buffer \var{buf} whose size is \var{buflen}
+ characters. It returns zero upon success, or \-1 if \var{dlist}
+ does not contain an \var{nth} element.
+\example
+ A delimited list of strings may be turned into an array of strings
+ as follows. For conciseness, all malloc error checking has been
+ omitted.
+#v+
+ int list_to_array (char *list, char delim, char ***ap)
+ {
+ unsigned int nth;
+ char **a;
+ char buf[1024];
+
+ /* Determine the size of the array */
+ nth = 0;
+ while (0 == SLextract_list_element (list, nth, delim, buf, sizeof(buf)))
+ nth++;
+
+ ap = (char **) SLmalloc ((nth + 1) * sizeof (char **));
+ nth = 0;
+ while (0 == SLextract_list_element (list, nth, delim, buf, sizeof(buf)))
+ {
+ a[nth] = SLmake_string (buf);
+ nth++;
+ }
+ a[nth] = NULL;
+ *ap = a;
+ return 0;
+ }
+#v-
+\seealso{SLmalloc, SLmake_string}
+\done
+
+
+#%+
+\function{SLprep_open_prep}
+\synopsis{??}
+\usage{int SLprep_open_prep (SLPreprocess_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{SLprep_close_prep}
+\synopsis{??}
+\usage{void SLprep_close_prep (SLPreprocess_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{SLprep_line_ok}
+\synopsis{??}
+\usage{int SLprep_line_ok (char *, SLPreprocess_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{SLdefine_for_ifdef}
+\synopsis{??}
+\usage{int SLdefine_for_ifdef (char *);}
+\description
+??
+\seealso{??}
+\done
+
+\function{SLang_Read_Line_Type * SLang_rline_save_line (SLang_RLine_Info_Type *);}
+\synopsis{??}
+\usage{SLang_Read_Line_Type * SLang_rline_save_line (SLang_RLine_Info_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLang_init_readline (SLang_RLine_Info_Type *);}
+\synopsis{??}
+\usage{int SLang_init_readline (SLang_RLine_Info_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLang_read_line (SLang_RLine_Info_Type *);}
+\synopsis{??}
+\usage{int SLang_read_line (SLang_RLine_Info_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLang_rline_insert (char *);}
+\synopsis{??}
+\usage{int SLang_rline_insert (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLrline_redraw (SLang_RLine_Info_Type *);}
+\synopsis{??}
+\usage{void SLrline_redraw (SLang_RLine_Info_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_flush_output (void);}
+\synopsis{??}
+\usage{int SLtt_flush_output (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_scroll_region(int, int);}
+\synopsis{??}
+\usage{void SLtt_set_scroll_region(int, int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_reset_scroll_region(void);}
+\synopsis{??}
+\usage{void SLtt_reset_scroll_region(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_reverse_video (int);}
+\synopsis{??}
+\usage{void SLtt_reverse_video (int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_bold_video (void);}
+\synopsis{??}
+\usage{void SLtt_bold_video (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_begin_insert(void);}
+\synopsis{??}
+\usage{void SLtt_begin_insert(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_end_insert(void);}
+\synopsis{??}
+\usage{void SLtt_end_insert(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_del_eol(void);}
+\synopsis{??}
+\usage{void SLtt_del_eol(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_goto_rc (int, int);}
+\synopsis{??}
+\usage{void SLtt_goto_rc (int, int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_delete_nlines(int);}
+\synopsis{??}
+\usage{void SLtt_delete_nlines(int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_delete_char(void);}
+\synopsis{??}
+\usage{void SLtt_delete_char(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_erase_line(void);}
+\synopsis{??}
+\usage{void SLtt_erase_line(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_normal_video(void);}
+\synopsis{??}
+\usage{void SLtt_normal_video(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_cls(void);}
+\synopsis{??}
+\usage{void SLtt_cls(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_beep(void);}
+\synopsis{??}
+\usage{void SLtt_beep(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_reverse_index(int);}
+\synopsis{??}
+\usage{void SLtt_reverse_index(int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_smart_puts(unsigned short *, unsigned short *, int, int);}
+\synopsis{??}
+\usage{void SLtt_smart_puts(unsigned short *, unsigned short *, int, int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_write_string (char *);}
+\synopsis{??}
+\usage{void SLtt_write_string (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_putchar(char);}
+\synopsis{??}
+\usage{void SLtt_putchar(char);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_init_video (void);}
+\synopsis{??}
+\usage{int SLtt_init_video (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_reset_video (void);}
+\synopsis{??}
+\usage{int SLtt_reset_video (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_get_terminfo(void);}
+\synopsis{??}
+\usage{void SLtt_get_terminfo(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_get_screen_size (void);}
+\synopsis{??}
+\usage{void SLtt_get_screen_size (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_set_cursor_visibility (int);}
+\synopsis{??}
+\usage{int SLtt_set_cursor_visibility (int);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLtt_initialize (char *);}
+\synopsis{??}
+\usage{int SLtt_initialize (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_enable_cursor_keys(void);}
+\synopsis{??}
+\usage{void SLtt_enable_cursor_keys(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_term_vtxxx(int *);}
+\synopsis{??}
+\usage{void SLtt_set_term_vtxxx(int *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_color_esc (int, char *);}
+\synopsis{??}
+\usage{void SLtt_set_color_esc (int, char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_wide_width(void);}
+\synopsis{??}
+\usage{void SLtt_wide_width(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_narrow_width(void);}
+\synopsis{??}
+\usage{void SLtt_narrow_width(void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_set_mouse_mode (int, int);}
+\synopsis{??}
+\usage{int SLtt_set_mouse_mode (int, int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_alt_char_set (int);}
+\synopsis{??}
+\usage{void SLtt_set_alt_char_set (int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_write_to_status_line (char *, int);}
+\synopsis{??}
+\usage{int SLtt_write_to_status_line (char *, int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_disable_status_line (void);}
+\synopsis{??}
+\usage{void SLtt_disable_status_line (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLtt_tgetstr (char *);}
+\synopsis{??}
+\usage{char *SLtt_tgetstr (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_tgetnum (char *);}
+\synopsis{??}
+\usage{int SLtt_tgetnum (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_tgetflag (char *);}
+\synopsis{??}
+\usage{int SLtt_tgetflag (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLtt_tigetent (char *);}
+\synopsis{??}
+\usage{char *SLtt_tigetent (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLtt_tigetstr (char *, char **);}
+\synopsis{??}
+\usage{char *SLtt_tigetstr (char *, char **);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLtt_tigetnum (char *, char **);}
+\synopsis{??}
+\usage{int SLtt_tigetnum (char *, char **);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{SLtt_Char_Type SLtt_get_color_object (int);}
+\synopsis{??}
+\usage{SLtt_Char_Type SLtt_get_color_object (int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_color_object (int, SLtt_Char_Type);}
+\synopsis{??}
+\usage{void SLtt_set_color_object (int, SLtt_Char_Type);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_color (int, char *, char *, char *);}
+\synopsis{??}
+\usage{void SLtt_set_color (int, char *, char *, char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_mono (int, char *, SLtt_Char_Type);}
+\synopsis{??}
+\usage{void SLtt_set_mono (int, char *, SLtt_Char_Type);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_add_color_attribute (int, SLtt_Char_Type);}
+\synopsis{??}
+\usage{void SLtt_add_color_attribute (int, SLtt_Char_Type);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLtt_set_color_fgbg (int, SLtt_Char_Type, SLtt_Char_Type);}
+\synopsis{??}
+\usage{void SLtt_set_color_fgbg (int, SLtt_Char_Type, SLtt_Char_Type);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLkp_define_keysym (char *, unsigned int);}
+\synopsis{??}
+\usage{int SLkp_define_keysym (char *, unsigned int);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLkp_init (void);}
+\synopsis{??}
+\usage{int SLkp_init (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLkp_getkey (void);}
+\synopsis{??}
+\usage{int SLkp_getkey (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLscroll_find_top (SLscroll_Window_Type *);}
+\synopsis{??}
+\usage{int SLscroll_find_top (SLscroll_Window_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLscroll_find_line_num (SLscroll_Window_Type *);}
+\synopsis{??}
+\usage{int SLscroll_find_line_num (SLscroll_Window_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{unsigned int SLscroll_next_n (SLscroll_Window_Type *, unsigned int);}
+\synopsis{??}
+\usage{unsigned int SLscroll_next_n (SLscroll_Window_Type *, unsigned int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{unsigned int SLscroll_prev_n (SLscroll_Window_Type *, unsigned int);}
+\synopsis{??}
+\usage{unsigned int SLscroll_prev_n (SLscroll_Window_Type *, unsigned int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLscroll_pageup (SLscroll_Window_Type *);}
+\synopsis{??}
+\usage{int SLscroll_pageup (SLscroll_Window_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLscroll_pagedown (SLscroll_Window_Type *);}
+\synopsis{??}
+\usage{int SLscroll_pagedown (SLscroll_Window_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{SLSig_Fun_Type *SLsignal (int, SLSig_Fun_Type *);}
+\synopsis{??}
+\usage{SLSig_Fun_Type *SLsignal (int, SLSig_Fun_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{SLSig_Fun_Type *SLsignal_intr (int, SLSig_Fun_Type *);}
+\synopsis{??}
+\usage{SLSig_Fun_Type *SLsignal_intr (int, SLSig_Fun_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLsig_block_signals (void);}
+\synopsis{??}
+\usage{int SLsig_block_signals (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLsig_unblock_signals (void);}
+\synopsis{??}
+\usage{int SLsig_unblock_signals (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLsystem (char *);}
+\synopsis{??}
+\usage{int SLsystem (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLadd_at_handler (long *, char *);}
+\synopsis{??}
+\usage{void SLadd_at_handler (long *, char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{void SLang_define_case(int *, int *);}
+\synopsis{??}
+\usage{void SLang_define_case(int *, int *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLang_init_case_tables (void);}
+\synopsis{??}
+\usage{void SLang_init_case_tables (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{unsigned char *SLang_regexp_match(unsigned char *, unsigned int, SLRegexp_Type *);}
+\synopsis{??}
+\usage{unsigned char *SLang_regexp_match(unsigned char *, unsigned int, SLRegexp_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLang_regexp_compile (SLRegexp_Type *);}
+\synopsis{??}
+\usage{int SLang_regexp_compile (SLRegexp_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLregexp_quote_string (char *, char *, unsigned int);}
+\synopsis{??}
+\usage{char *SLregexp_quote_string (char *, char *, unsigned int);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLcmd_execute_string (char *, SLcmd_Cmd_Table_Type *);}
+\synopsis{??}
+\usage{int SLcmd_execute_string (char *, SLcmd_Cmd_Table_Type *);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLsearch_init (char *, int, int, SLsearch_Type *);}
+\synopsis{??}
+\usage{int SLsearch_init (char *, int, int, SLsearch_Type *);}
+\description
+??
+/* This routine must first be called before any search can take place.
+ * The second parameter specifies the direction of the search: greater than
+ * zero for a forwrd search and less than zero for a backward search. The
+ * third parameter specifies whether the search is case sensitive or not.
+ * The last parameter is a pointer to a structure that is filled by this
+ * function and it is this structure that must be passed to SLsearch.
+ */
+\seealso{??}
+\done
+
+
+\function{unsigned char *SLsearch (unsigned char *, unsigned char *, SLsearch_Type *);}
+\synopsis{??}
+\usage{unsigned char *SLsearch (unsigned char *, unsigned char *, SLsearch_Type *);}
+\description
+??
+/* To use this routine, you must first call 'SLsearch_init'. Then the first
+ * two parameters p1 and p2 serve to define the region over which the search
+ * is to take place. The third parameter is the structure that was previously
+ * initialized by SLsearch_init.
+ *
+ * The routine returns a pointer to the match if found otherwise it returns
+ * NULL.
+ */
+\seealso{??}
+\done
+
+
+\function{SLcomplex_abs}
+\synopsis{Returns the norm of a complex number}
+\usage{double SLcomplex_abs (double *z)}}
+\description
+ The \var{SLcomplex_abs} function returns the absolute value or the
+ norm of the complex number given by \var{z}.
+\seealso{SLcomplex_times}
+\done
+
+
+\function{double *SLcomplex_times (double *, double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_times (double *, double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_divide (double *, double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_divide (double *, double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_sin (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_sin (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_cos (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_cos (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_tan (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_tan (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_asin (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_asin (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_acos (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_acos (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_atan (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_atan (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_exp (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_exp (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_log (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_log (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_log10 (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_log10 (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_sqrt (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_sqrt (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_sinh (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_sinh (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_cosh (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_cosh (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_tanh (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_tanh (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_pow (double *, double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_pow (double *, double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double SLmath_hypot (double x, double y);}
+\synopsis{??}
+\usage{double SLmath_hypot (double x, double y);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+extern double *SLcomplex_asinh (double *, double *);
+\function{double *SLcomplex_acosh (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_acosh (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{double *SLcomplex_atanh (double *, double *);}
+\synopsis{??}
+\usage{double *SLcomplex_atanh (double *, double *);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+
+\function{char *SLdebug_malloc (unsigned long);}
+\synopsis{??}
+\usage{char *SLdebug_malloc (unsigned long);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLdebug_calloc (unsigned long, unsigned long);}
+\synopsis{??}
+\usage{char *SLdebug_calloc (unsigned long, unsigned long);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLdebug_realloc (char *, unsigned long);}
+\synopsis{??}
+\usage{char *SLdebug_realloc (char *, unsigned long);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLdebug_free (char *);}
+\synopsis{??}
+\usage{void SLdebug_free (char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{void SLmalloc_dump_statistics (void);}
+\synopsis{??}
+\usage{void SLmalloc_dump_statistics (void);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLstrcpy(register char *, register char *);}
+\synopsis{??}
+\usage{char *SLstrcpy(register char *, register char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{int SLstrcmp(register char *, register char *);}
+\synopsis{??}
+\usage{int SLstrcmp(register char *, register char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+\function{char *SLstrncpy(char *, register char *, register int);}
+\synopsis{??}
+\usage{char *SLstrncpy(char *, register char *, register int);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{void SLmemset (char *, char, int);}
+\synopsis{??}
+\usage{void SLmemset (char *, char, int);}
+\description
+??
+\seealso{??}
+\done
+
+
+extern int SLang_add_intrinsic_array (char *, /* name */
+ unsigned char, /* type */
+ int, /* readonly */
+ VOID_STAR, /* data */
+ unsigned int, ...); /* num dims */
+
+
+
+\function{void SLexpand_escaped_string (register char *, register char *, register char *);}
+\synopsis{??}
+\usage{void SLexpand_escaped_string (register char *, register char *, register char *);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{void SLmake_lut (unsigned char *, unsigned char *, unsigned char);}
+\synopsis{??}
+\usage{void SLmake_lut (unsigned char *, unsigned char *, unsigned char);}
+\description
+??
+\seealso{??}
+\done
+
+
+
+\function{int SLang_guess_type (char *);}
+\synopsis{??}
+\usage{int SLang_guess_type (char *);}
+\description
+??
+\seealso{??}
+\done
+
+#%-
+
+\end{\documentstyle}
diff --git a/libslang/doc/tm/cslang.tm b/libslang/doc/tm/cslang.tm
new file mode 100644
index 0000000..acc82c6
--- /dev/null
+++ b/libslang/doc/tm/cslang.tm
@@ -0,0 +1,2033 @@
+#c -*- mode: tm; mode: fold -*-
+
+#c text-macro definitions #%{{{
+#i linuxdoc.tm
+
+#d slang \bf{S-Lang}
+#d slrn \bf{slrn}
+#d jed \bf{jed}
+#d key#1 <tt>$1</tt>
+#d footnote#1 <footnote>$1</footnote>
+#d grp#1 <tt>$1</tt>
+#d file#1 <tt>$1</tt>
+#d -1 <tt>-1</tt>
+#d 0 <tt>0</tt>
+#d 1 <tt>1</tt>
+
+#d kw#1 \tt{$1}
+#d exmp#1 \tt{$1}
+#d var#1 \tt{$1}
+
+#d cfun#1 \tt{$1}
+#d ivar#1 \tt{$1}
+#d ifun#1 \tt{$1}
+#d exfile#1 \tt{$1}
+#d exns#1 \tt{$1}
+#d exstr#1 \tt{"$1"}
+
+#d ldots ...
+#d times *
+#d sc#1 \tt{$1}
+#d verb#1 \tt{$1}
+#d sldxe \bf{sldxe}
+#d url#1 <htmlurl url="$1" name="$1">
+#d slang-library-reference \bf{The \slang Library Reference}
+#d chapter#1 <chapt>$1<p>
+#d tag#1 <tag>$1</tag>
+#d appendix <appendix>
+
+#d kbd#1 <tt>$1</tt>
+
+#d documentstyle book
+
+#%}}}
+
+\linuxdoc
+
+\begin{\documentstyle}
+
+\title S-Lang Library C Programmer's Guide, V1.4.9
+\author John E. Davis, \tt{davis@space.mit.edu}
+\date \__today__
+
+\toc
+
+#i preface.tm
+
+\chapter{Introduction} #%{{{
+
+ \slang is a C programmer's library that includes routines for the rapid
+ development of sophisticated, user friendly, multi-platform applications.
+ The \slang library includes the following:
+
+\begin{itemize}
+\item Low level tty input routines for reading single characters at a time.
+\item Keymap routines for defining keys and manipulating multiple keymaps.
+\item A high-level keyprocessing interface (\verb{SLkp}) for
+ handling function and arrow keys.
+\item High level screen management routines for manipulating both
+ monochrome and color terminals. These routines are \em{very}
+ efficient. (\tt{SLsmg})
+\item Low level terminal-independent routines for manipulating the display
+ of a terminal. (\tt{SLtt})
+\item Routines for reading single line input with line editing and recall
+ capabilities. (\tt{SLrline})
+\item Searching functions: both ordinary searches and regular expression
+ searches. (\tt{SLsearch})
+\item An embedded stack-based language interpreter with a C-like syntax.
+\end{itemize}
+
+ The library is currently available for OS/2, MSDOS, Unix, and VMS
+ systems. For the most part, the interface to library routines has
+ been implemented in such a way that it appears to be platform
+ independent from the point of view of the application. In addition,
+ care has been taken to ensure that the routines are ``independent''
+ of one another as much as possible. For example, although the
+ keymap routines require keyboard input, they are not tied to
+ \slang's keyboard input routines--- one can use a different keyboard
+ \verb{getkey} routine if one desires. This also means that linking
+ to only part of the \slang library does not pull the whole library
+ into the application. Thus, \slang applications tend to be
+ relatively small in comparison to programs that use libraries with
+ similar capabilities.
+
+#%}}}
+
+\chapter{Interpreter Interface} #%{{{
+
+ The \slang library provides an interpreter that when embedded into
+ an application, makes the application extensible. Examples of
+ programs that embed the interpreter include the \jed editor and the
+ \slrn newsreader.
+
+ Embedding the interpreter is easy. The hard part is to decide what
+ application specific built-in or intrinsic functions should be
+ provided by the application. The \slang library provides some
+ pre-defined intrinsic functions, such as string processing
+ functions, and simple file input-output routines. However, the
+ basic philosophy behind the interpreter is that it is not a
+ standalone program and it derives much of its power from the
+ application that embeds it.
+
+\sect{Embedding the Interpreter} #%{{{
+
+ Only one function needs to be called to embed the \slang interpreter
+ into an application: \cfun{SLang_init_slang}. This function
+ initializes the interpreter's data structures and adds some intrinsic
+ functions:
+#v+
+ if (-1 == SLang_init_slang ())
+ exit (EXIT_FAILURE);
+#v-
+ This function does not provide file input output intrinsic nor does
+ it provide mathematical functions. To make these as well as some
+ posix system calls available use
+#v+
+ if ((-1 == SLang_init_slang ()) /* basic interpreter functions */
+ || (-1 == SLang_init_slmath ()) /* sin, cos, etc... */
+ || (-1 == SLang_init_stdio ()) /* stdio file I/O */
+ || (-1 == SLang_init_posix_dir ()) /* mkdir, stat, etc. */
+ || (-1 == SLang_init_posix_process ()) /* getpid, umask, etc. */
+ )
+ exit (EXIT_FAILURE);
+#v-
+ If you intend to enable all intrinsic functions, then it is simpler
+ to initialize the interpreter via
+#v+
+ if (-1 == SLang_init_all ())
+ exit (EXIT_FAILURE);
+#v-
+ See the \slang-run-time-library for more information about the
+ intrinsic functions.
+
+
+#%}}}
+
+\sect{Calling the Interpreter} #%{{{
+
+ There are several ways of calling the interpreter. The two most common
+ method is to load a file containing \slang code, or to load a
+ string.
+
+\sect1{Loading Files}
+ The \cfun{SLang_load_file} and \cfun{SLns_load_file} functions may
+ be used to interpret a file. Both these functions return zero if
+ successful, or \-1 upon failure. If either of these functions fail,
+ the interpreter will accept no more code unless the error state is
+ cleared. This is done by calling \cfun{SLang_restart} function to
+ set the interpreter to its default state, \em{and} setting
+ \ivar{SLang_Error} to 0, e.g.,
+#v+
+ if (-1 == SLang_load_file ("site.sl"))
+ {
+ /* Clear the error and rest the interpreter */
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+#v-
+
+ When a file is loaded via \cfun{SLang_load_file}, any non-public
+ variables and functions defined in the file will be placed into a
+ namespace that is local to the file itself. The
+ \cfun{SLns_load_file} function may be used to load a file using a
+ specified namespace, e.g.,
+#v+
+ if (-1 == SLns_load_file ("site.sl", "NS"))
+ {
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+#v-
+ will load \exfile{site.sl} into a namespace called \exns{NS}. If such a
+ namespace does not exist, then it will be created.
+
+ Both the \cfun{SLang_load_file} and \cfun{SLns_load_file} functions
+ search for files along an application-specified search path. This
+ path may be set using the \cfun{SLpath_set_load_path} function, as
+ well as from interpeted code via the \ifun{set_slang_load_path}
+ function. By default, no search path is defined.
+
+ Files are searched as follows: If the name begins with the
+ equivalent of \exstr{./} or \exstr{../}, then it is searched for
+ with respect to the current directory, and not along the load-path.
+ If no such file exists, then an error will be generated. Otherwise,
+ the file is searched for in each of the directories of the load-path
+ by concatenating the path element with the specified file name. The
+ first such file found to exist by this process will be loaded. If a
+ matching file still has not been found, and the file name lacks an
+ extension, then the path is searched with \exstr{.sl} and
+ \exstr{.slc} appended to the filename. If two such files are found
+ (one ending with \exstr{.sl} and the other with \exstr{.slc}), then
+ the more recent of the two will be used. If no matching file has
+ been found by this process, then the search will cease and an error
+ generated.
+
+ The search path is a delimiter separated list of directories that
+ specify where the interpreter looks for files. By default, the
+ value of the delimiter is OS-dependent following the convention of
+ the underlying OS. For example, on Unix the delimiter is
+ represented by a colon, on DOS/Windows it is a semi-colon, and on
+ VMS it is a space. The \cfun{SLpath_set_delimiter} and
+ \cfun{SLpath_get_delimiter} may be used to set and query the
+ delimiter's value, respectively.
+
+\sect1{Loading Strings}
+ There are several other mechanisms for interacting with the
+ interpreter. For example, the \cfun{SLang_load_string} function
+ loads a string into the interpreter and interprets it:
+#v+
+ if (-1 == SLang_load_string ("message (\"hello\");"))
+ {
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+#v-
+ Similarly, the \cfun{SLns_load_string} function may be used to load
+ a string into a specified namespace.
+
+ Typically, an interactive application will load a file via
+ \cfun{SLang_load_file} and then go into a loop that consists of
+ reading lines of input and sending them to the interpreter, e.g.,
+#v+
+ while (EOF != fgets (buf, sizeof (buf), stdin))
+ {
+ if (-1 == SLang_load_string (buf))
+ SLang_restart (1);
+ SLang_Error = 0;
+ }
+#v-
+
+ Finally, some applications such as \jed and \slrn use another method of
+ interacting with the interpreter. They read key sequences from the
+ keyboard and map those key sequences to interpreter functions via
+ the \slang keymap interface.
+
+#%}}}
+
+\sect{Intrinsic Functions} #%{{{
+
+ An intrinsic function is simply a function that is written in C and
+ is made available to the interpreter as a built-in function. For
+ this reason, the words `intrinsic' and `built-in' are often used
+ interchangeably.
+
+ Applications are expected to add application specific functions to
+ the interpreter. For example, \jed adds nearly 300 editor-specific
+ intrinsic functions. The application designer should think
+ carefully about what intrinsic functions to add to the interpreter.
+
+\sect1{Restrictions on Intrinsic Functions} #%{{{
+
+ When implementing intrinsic functions, it is necessary to follow a
+ few rules to cooperate with the interpreter.
+
+ The C version of an intrinsic function takes only pointer arguments.
+ This is because when the interpreter calls an intrinsic function, it
+ passes values to the function by reference and \em{not} by value. For
+ example, intrinsic with the declarations:
+#v+
+ int intrinsic_0 (void);
+ int intrinsic_1 (char *s);
+ void intrinsic_2 (char *s, int *i);
+ void intrinsic_3 (int *i, double *d, double *e);
+#v-
+ are all valid. However,
+#v+
+ int invalid_1 (char *s, int len);
+#v-
+ is not valid since the \var{len} parameter is not a pointer.
+
+ The return value of an intrinsic function must be one of the
+ following types: \var{void}, \var{char}, \var{short}, \var{int},
+ \var{long}, \var{double}, \var{char *}, as well as unsigned versions
+ of the integer types. A function such as
+#v+
+ int *invalid (void);
+#v-
+ is not permitted since \var{int*} is not a valid return-type for an
+ intrinsic function. Any other type of value can be passed back to
+ the interpreter by explicitly pushing the object onto the
+ interpreter's stack via the appropriate "push" function.
+
+ The current implementation limits the number of arguments of an
+ intrinsic function to \exmp{7}. The "pop" functions can be used to
+ allow the function to take an arbitrary number as seen from an
+ interpreter script.
+
+ Another restriction is that the intrinsic function should regard all its
+ parameters as pointers to constant objects and make no attempt to
+ modify the value to which they point. For example,
+#v+
+ void truncate (char *s)
+ {
+ s[0] = 0;
+ }
+#v-
+ is illegal since the function modifies the string \var{s}.
+
+
+#%}}}
+
+\sect1{Adding a New Intrinsic} #%{{{
+
+ There are two basic mechanisms for adding an intrinsic function to the
+ interpreter: \cfun{SLadd_intrinsic_function} and
+ \cfun{SLadd_intrin_fun_table}. Functions may be added to a specified
+ namespace via \cfun{SLns_add_intrinsic_function} and
+ \cfun{SLns_add_intrin_fun_table} functions.
+
+ As an specific example, consider a function that will cause the
+ program to exit via the \var{exit} C library function. It is not
+ possible to make this function an intrinsic because it does not meet
+ the specifications for an intrinsic function that were described
+ earlier. However, one can call \var{exit} from a function that is
+ suitable, e.g.,
+#v+
+ void intrin_exit (int *code)
+ {
+ exit (*code);
+ }
+#v-
+ This function may be made available to the interpreter as an
+ intrinsic via the \cfun{SLadd_intrinsic_function} routine:
+#v+
+ if (-1 == SLadd_intrinsic_function ("exit", (FVOID_STAR) intrin_exit,
+ SLANG_VOID_TYPE, 1,
+ SLANG_INT_TYPE))
+ exit (EXIT_FAILURE);
+#v-
+ This statement basically tells the interpreter that
+ \var{intrin_exit} is a function that returns nothing and takes a
+ single argument: a pointer to an integer (\var{SLANG_INT_TYPE}).
+ A user can call this function from within the interpreter
+ via
+#v+
+ message ("Calling the exit function");
+ exit (0);
+#v-
+ After printing a message, this will cause the \var{intrin_exit}
+ function to execute, which in turn calls \var{exit}.
+
+ The most convenient mechanism for adding new intrinsic functions is
+ to create a table of \cfun{SLang_Intrin_Fun_Type} objects and add the
+ table via the \cfun{SLadd_intrin_fun_table} function. The table will
+ look like:
+#v+
+ SLang_Intrin_Fun_Type My_Intrinsics [] =
+ {
+ /* table entries */
+ MAKE_INTRINSIC_N(...),
+ MAKE_INTRINSIC_N(...),
+ .
+ .
+ MAKE_INTRINSIC_N(...),
+ SLANG_END_INTRIN_FUN_TABLE
+ };
+#v-
+ Construction of the table entries may be facilitated using a set of
+ \var{MAKE_INTRINSIC} macros defined in \var{slang.h}. The main
+ macro is called \var{MAKE_INTRINSIC_N} and takes 11 arguments:
+#v+
+ MAKE_INTRINSIC_N(name, funct-ptr, return-type, num-args,
+ arg-1-type, arg-2-type, ... arg-7-type)
+#v-
+ Here \var{name} is the name of the intrinsic function that the
+ interpreter is to give to the function. \var{func-ptr} is a pointer
+ to the intrinsic function taking \var{num-args} and returning
+ \var{ret-type}. The final \exmp{7} arguments specifiy the argument
+ types. For example, the \var{intrin_exit} intrinsic described above
+ may be added to the table using
+#v+
+ MAKE_INTRINSIC_N("exit", intrin_exit, SLANG_VOID_TYPE, 1,
+ SLANG_INT_TYPE, 0,0,0,0,0,0)
+#v-
+
+ While \var{MAKE_INTRINSIC_N} is the main macro for constructing
+ table entries, \var{slang.h} defines other macros that may prove
+ useful. In particular, an entry for the \var{intrin_exit} function
+ may also be created using any of the following forms:
+#v+
+ MAKE_INTRINSIC_1("exit", intrin_exit, SLANG_VOID_TYPE, SLANG_INT_TYPE)
+ MAKE_INTRINSIC_I("exit", intrin_exit, SLANG_VOID_TYPE)
+#v-
+ See \var{slang.h} for related macros. You are also encouraged to
+ look at, e.g., \var{slang/src/slstd.c} for a more extensive examples.
+
+ The table may be added via the \cfun{SLadd_intrin_fun_table}
+ function, e.g.,
+#v+
+ if (-1 == SLadd_intrin_fun_table (My_Intrinsics, NULL))
+ {
+ /* an error occurred */
+ }
+#v-
+ Please note that there is no need to load a given table more than
+ once, and it is considered to be an error on the part of the
+ application it adds the same table multiple times. For performance
+ reasons, no checking is performed by the library to see if a table
+ has already been added.
+
+ Earlier it was mentioned that intrinsics may be added to a specified
+ namespace. To this end, one must first get a pointer to the
+ namespace via the \cfun{SLns_create_namespace} function. The
+ following example illustrates how this function is used to add the
+ \var{My_Intrinsics} table to a namespace called \exmp{my}:
+#v+
+ SLang_NameSpace_Type *ns = SLns_create_namespace ("my");
+ if (ns == NULL)
+ return -1;
+
+ return SLns_add_intrin_fun_table (ns, My_Intrinsics, "__MY__"));
+#v-
+
+#%}}}
+
+\sect1{More Complicated Intrinsics} #%{{{
+ The intrinsic functions described in the previous example were
+ functions that took a fixed number of arguments. In this section we
+ explore more complex intrinsics such as those that take a variable
+ number of arguments.
+
+ Consider a function that takes two double precision numbers and
+ returns the lesser:
+#v+
+ double intrin_min (double *a, double *b)
+ {
+ if (*a < *b) return *a;
+ return *b;
+ }
+#v-
+ This function may be added to a table of intrinsics using
+#v+
+ MAKE_INTRINSIC_2("vmin", intrin_min, SLANG_DOUBLE_TYPE,
+ SLANG_DOUBLE_TYPE, SLANG_DOUBLE_TYPE)
+#v-
+ It is useful to extend this function to take an arbitray number of
+ arguments and return the lesser. Consider the following variant:
+#v+
+ double intrin_min_n (int *num_ptr)
+ {
+ double min_value, x;
+ unsigned int num = (unsigned int) *num_ptr;
+
+ if (-1 == SLang_pop_double (&min_value, NULL, NULL))
+ return 0.0;
+ num--;
+
+ while (num > 0)
+ {
+ num--;
+ if (-1 == SLang_pop_double (&x, NULL, NULL))
+ return 0.0;
+ if (x < min_value) min_value = x;
+ }
+ return min_value;
+ }
+#v-
+ Here the number to compare is passed to the function and the actual
+ numbers are removed from the stack via the \cfun{SLang_pop_double}
+ function. A suitable table entry for it is
+#v+
+ MAKE_INTRINSIC_I("vmin", intrin_min_n, SLANG_DOUBLE_TYPE)
+#v-
+ This function would be used in an interpreter script via a statement
+ such as
+#v+
+ variable xmin = vmin (x0, x1, x2, x3, x4, 5);
+#v-
+ which computes the smallest of \exmp{5} values.
+
+ The problem with this intrinsic function is that the user must
+ explicitly specify how many numbers to compare. It would be more
+ convenient to simply use
+#v+
+ variable xmin = vmin (x0, x1, x2, x3, x4);
+#v-
+ An intrinsic function can query the value of the variable
+ \var{SLang_Num_Function_Args} to obtain the necessary information:
+#v+
+ double intrin_min (void)
+ {
+ double min_value, x;
+
+ unsigned int num = SLang_Num_Function_Args;
+
+ if (-1 == SLang_pop_double (&min_value, NULL, NULL))
+ return 0.0;
+ num--;
+
+ while (num > 0)
+ {
+ num--;
+ if (-1 == SLang_pop_double (&x, NULL, NULL))
+ return 0.0;
+ if (x < min_value) min_value = x;
+ }
+ return min_value;
+ }
+#v-
+ This may be declared as an intrinsic using:
+#v+
+ MAKE_INTRINSIC_0("vmin", intrin_min, SLANG_DOUBLE_TYPE)
+#v-
+
+
+#%}}}
+
+#%}}}
+
+\sect{Intrinsic Variables} #%{{{
+
+ It is possible to access an application's global variables from
+ within the interpreter. The current implementation supports the
+ access of variables of type \var{int}, \var{char *}, and
+ \var{double}.
+
+ There are two basic methods of making an intrinsic variable
+ available to the interpreter. The most straight forward method is
+ to use the function \cfun{SLadd_intrinsic_variable}:
+#v+
+ int SLadd_intrinsic_variable (char *name, VOID_STAR addr,
+ unsigned char data_type,
+ int read_only);
+#v-
+ For example, suppose that \var{I} is an integer variable, e.g.,
+#v+
+ int I;
+#v-
+ One can make it known to the interpreter as \var{I_Variable} via a
+ statement such as
+#v+
+ if (-1 == SLadd_intrinsic_variable ("I_Variable", &I,
+ SLANG_INT_TYPE, 0))
+ exit (EXIT_FAILURE);
+#v-
+ Similarly, if \var{S} is declared as
+#v+
+ char *S;
+#v-
+ then
+#v+
+ if (-1 == SLadd_intrinsic_variable ("S_Variable", &S,
+ SLANG_STRING_TYPE, 1))
+ exit (EXIT_FAILURE);
+#v-
+ makes \var{S} available as a \em{read-only} variable with the name
+ \var{S_Variable}. Note that if a pointer variable is made available
+ to the interpreter, its value is managed by the interpreter and
+ not the application. For this reason, it is recommended that such
+ variables be declared as \em{read-only}.
+
+ It is important to note that if \var{S} were declared as an array of
+ characters, e.g.,
+#v+
+ char S[256];
+#v-
+ then it would not be possible to make it directly available to the
+ interpreter. However, one could create a pointer to it, i.e.,
+#v+
+ char *S_Ptr = S;
+#v-
+ and make \var{S_Ptr} available as a read-only variable.
+
+ One should not make the mistake of trying to use the same address
+ for different variables as the following example illustrates:
+#v+
+ int do_not_try_this (void)
+ {
+ static char *names[3] = {"larry", "curly", "moe"};
+ unsigned int i;
+
+ for (i = 0; i < 3; i++)
+ {
+ int value;
+ if (-1 == SLadd_intrinsic_variable (names[i], (VOID_STAR) &value,
+ SLANG_INT_TYPE, 1))
+ return -1;
+ }
+ return 0;
+ }
+#v-
+ Not only does this piece of code create intrinsic variables that use
+ the same address, it also uses the address of a local variable that
+ will go out of scope.
+
+ The most convenient method for adding many intrinsic variables to
+ the interpreter is to create an array of \var{SLang_Intrin_Var_Type}
+ objects and then add the array via \cfun{SLadd_intrin_var_table}.
+ For example, the array
+#v+
+ static SLang_Intrin_Var_Type Intrin_Vars [] =
+ {
+ MAKE_VARIABLE("I_Variable", &I, SLANG_INT_TYPE, 0),
+ MAKE_VARIABLE("S_Variable", &S_Ptr, SLANG_STRING_TYPE, 1),
+ SLANG_END_TABLE
+ };
+#v-
+ may be added via
+#v+
+ if (-1 == SLadd_intrin_var_table (Intrin_Vars, NULL))
+ exit (EXIT_FAILURE);
+#v-
+ It should be rather obvious that the arguments to the
+ \var{MAKE_VARIABLE} macro correspond to the parameters of the
+ \cfun{SLadd_intrinsic_variable} function.
+
+ Finally, variables may be added to a specific namespace via the
+ SLns_add_intrin_var_table and SLns_add_intrinsic_variable functions.
+
+#%}}}
+
+\sect{Aggregate Data Objects} #%{{{
+ An aggregate data object is an object that can contain more than one
+ data value. The \slang interpreter supports several such objects:
+ arrays, structure, and associative arrays. In the following
+ sections, information about interacting with these objects is given.
+
+\sect1{Arrays} #%{{{
+ An intrinsic function may interact with an array in several different
+ ways. For example, an intrinsic may create an array and return it.
+ The basic functions for manipulating arrays include:
+#v+
+ SLang_create_array
+ SLang_pop_array_of_type
+ SLang_push_array
+ SLang_free_array
+ SLang_get_array_element
+ SLang_set_array_element
+#v-
+ The use of these functions will be illustrated via a few simple
+ examples.
+
+ The first example shows how to create an return an array of strings
+ to the interpreter. In particular, the names of the four seasons of
+ the year will be returned:
+#v+
+ void months_of_the_year (void)
+ {
+ static char *seasons[4] =
+ {
+ "Spring", "Summer", "Autumn", "Winter"
+ };
+ SLang_Array_Type *at;
+ int i, four;
+
+ four = 4;
+ at = SLang_create_array (SLANG_STRING_TYPE, 0, NULL, &four, 1);
+ if (at == NULL)
+ return;
+
+ /* Now set the elements of the array */
+ for (i = 0; i < 4; i++)
+ {
+ if (-1 == SLang_set_array_element (at, &i, &seasons[i]))
+ {
+ SLang_free_array (at);
+ return;
+ }
+ }
+
+ (void) SLang_push_array (at, 0);
+ SLang_free_array (at);
+ }
+#v-
+ This example illustrates several points. First of all, the
+ \cfun{SLang_create_array} function was used to create a 1 dimensional
+ array of 4 strings. Since this function could fail, its return value
+ was checked. Then the \cfun{SLang_set_array_element} function was
+ used to set the elements of the newly created array. Note that the
+ address containing the value of the array element was passed and not
+ the value of the array element itself. That is,
+#v+
+ SLang_set_array_element (at, &i, seasons[i])
+#v-
+ was not used. The return value from this function was also checked
+ because it too could also fail. Finally, the array was pushed onto
+ the interpreter's stack and then it was freed. It is important to
+ understand why it was freed. This is because arrays are
+ reference-counted. When the array was created, it was returned with
+ a reference count of \var{1}. When it was pushed, the reference
+ count was bumped up to \var{2}. Then since it was nolonger needed by
+ the function, \cfun{SLang_free_array} was called to decrement the
+ reference count back to \var{1}. For convenience, the second
+ argument to \cfun{SLang_push_array} determines whether or not it is to
+ also free the array. So, instead of the two function calls:
+#v+
+ (void) SLang_push_array (at, 0);
+ SLang_free_array (at);
+#v-
+ it is preferable to combine them as
+#v+
+ (void) SLang_push_array (at, 1);
+#v-
+
+ The second example returns a diagonal array of a specified size to
+ the stack. A diagonal array is a 2-d array with all elements zero
+ except for those along the diagonal, which have a value of one:
+#v+
+ void make_diagonal_array (int n)
+ {
+ SLang_Array_Type *at;
+ int dims[2];
+ int i, one;
+
+ dims[0] = dims[1] = n;
+ at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, dims, 2);
+ if (at == NULL)
+ return;
+
+ one = 1;
+ for (i = 0; i < n; i++)
+ {
+ dims[0] = dims[1] = i;
+ if (-1 == SLang_set_array_element (at, dims, &one))
+ {
+ SLang_free_array (at);
+ return;
+ }
+ }
+
+ (void) SLang_push_array (at, 1);
+ }
+#v-
+ In this example, only the diagonal elements of the array were set.
+ This is bacause when the array was created, all its elements were
+ set to zero.
+
+ Now consider an example that acts upon an existing array. In
+ particular, consider one that computes the trace of a 2-d matrix,
+ i.e., the sum of the diagonal elements:
+#v+
+ double compute_trace (void)
+ {
+ SLang_Array_Type *at;
+ double trace;
+ int dims[2];
+
+ if (-1 == SLang_pop_array_of_type (&at, SLANG_DOUBLE_TYPE))
+ return 0.0;
+
+ /* We want a 2-d square matrix. If the matrix is 1-d and has only one
+ element, then return that element. */
+ trace = 0.0;
+ if (((at->num_dims == 1) && (at->dims[0] == 1))
+ || ((at->num_dims == 2) && (at->dims[0] == at->dims[1])))
+ {
+ double dtrace;
+ int n = at->dims[0];
+
+ for (i = 0; i < n; i++)
+ {
+ dims[0] = dims[1] = i;
+ (void) SLang_get_array_element (at, &dims, &dtrace);
+ trace += dtrace;
+ }
+ }
+ else SLang_verror (SL_TYPE_MISMATCH, "Expecting a square matrix");
+
+ SLang_free_array (at);
+ return trace;
+ }
+#v-
+ In this example, \cfun{SLang_pop_array_of_type} was used to pop an
+ array of doubles from the stack. This function will make implicit
+ typecasts in order to return an array of the requested type.
+
+#%}}}
+
+\sect1{Structures} #%{{{
+
+ For the purposes of this section, we shall differentiate structures
+ according to whether or not they correspond to an application defined
+ C structure. Those that do are called intrinsic structures, and
+ those do not are called \slang interpreter structures.
+
+\sect2{Interpreter Structures}
+
+ The following simple example shows one method that may be used to
+ create and return a structure with a string and integer field to the
+ interpreter's stack:
+#v+
+ int push_struct_example (char *string_value, int int_value)
+ {
+ char *field_names[2];
+ unsigned char field_types[2];
+ VOID_STAR field_values[2];
+
+ field_names[0] = "string_field";
+ field_types[0] = SLANG_STRING_TYPE;
+ field_values[0] = &string_value;
+
+ field_names[1] = "int_field";
+ field_types[1] = SLANG_INT_TYPE;
+ field_values[1] = &int_value;
+
+ if (-1 == SLstruct_create_struct (2, field_names,
+ field_types, field_values))
+ return -1;
+ return 0;
+ }
+#v-
+ Here, \cfun{SLstruct_create_struct} is used to push a
+ structure with the specified field names and values onto the
+ interpreter's stack.
+
+ A simpler mechanism exists provided that one has already defined a C
+ structure with a description of how the structure is laid out. For
+ example, consider a C structure defined by
+#v+
+ typedef struct
+ {
+ char *s;
+ int i;
+ }
+ SI_Type;
+#v-
+ Its layout may be specified via a table of
+ \var{SLang_CStruct_Field_Type} entries:
+#v+
+ SLang_CStruct_Field_Type SI_Type_Layout [] =
+ {
+ MAKE_CSTRUCT_FIELD(SI_Type, s, "string_field", SLANG_STRING_TYPE, 0),
+ MAKE_CSTRUCT_FIELD(SI_Type, i, "int_field", SLANG_INT_TYPE, 0),
+ SLANG_END_CSTRUCT_TABLE
+ };
+#v-
+ Here, MAKE_CSTRUCT_FIELD is a macro taking 5 arguments:
+#v+
+ MAKE_CSTRUCT_FIELD(C-structure-type,
+ C-field-name,
+ slang-field-name,
+ slang-data-type,
+ is-read-only)
+#v-
+ The first argument is the structure type, the second is the name of
+ a field of the structure, the third is a string that specifies the
+ name of the corresponding field of the \slang structure, the fourth
+ argument specifies the field's type, and the last argument
+ specifies whether or not the field should be regarded as read-only.
+
+ Once the layout of the structure has been specified, pushing a
+ \slang version of the structure is trival:
+#v+
+ int push_struct_example (char *string_value, int int_value)
+ {
+ SI_Type si;
+
+ si.s = string_value;
+ si.i = int_value;
+ return SLang_push_cstruct ((VOID_STAR)&si, SI_Type_Layout);
+ }
+#v-
+
+ This mechanism of structure creation also permits a \slang
+ structure to be passed to an intrinsic function through the use of
+ the SLang_pop_cstruct routine, e.g.,
+#v+
+ void print_si_struct (void)
+ {
+ SI_Type si;
+ if (-1 == SLang_pop_cstruct ((VOID_STAR)&si, SI_Type_Layout))
+ return;
+ printf ("si.i=%d", si.i);
+ printf ("si.s=%s", si.s);
+ SLang_free_cstruct ((VOID_STAR)&si, SI_Type_Layout);
+ }
+#v-
+ Assuming \exmp{print_si_struct} exists as an intrinsic function,
+ the \slang code
+#v+
+ variable s = struct {string_field, int_field};
+ s.string_field = "hello";
+ s.int_field = 20;
+ print_si_struct (s);
+#v-
+ would result in the display of
+#v+
+ si.i=20;
+ si.s=hello
+#v-
+ Note that the \cfun{SLang_free_cstruct} function was called after
+ the contents of \exmp{si} were nolonger needed. This was necessary
+ because \cfun{SLang_pop_cstruct} allocated memory to set the
+ \exmp{char *s} field of \exmp{si}. Calling
+ \cfun{SLang_free_cstruct} frees up such memory.
+
+ Now consider the following:
+#v+
+ typedef struct
+ {
+ pid_t pid;
+ gid_t group;
+ }
+ X_t;
+#v-
+ How should the layout of this structure be defined? One might be
+ tempted to use:
+#v+
+ SLang_CStruct_Field_Type X_t_Layout [] =
+ {
+ MAKE_CSTRUCT_FIELD(X_t, pid, "pid", SLANG_INT_TYPE, 0),
+ MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_INT_TYPE, 0),
+ SLANG_END_CSTRUCT_TABLE
+ };
+#v-
+ However, this assumes \exmp{pid_t} and \exmp{gid_t} have been
+ typedefed as ints. But what if \exmp{gid_t} is a \exmp{short}? In
+ such a case, using
+#v+
+ MAKE_CSTRUCT_FIELD(X_t, group, "group", SLANG_SHORT_TYPE, 0),
+#v-
+ would be the appropriate entry for the \exmp{group} field. Of
+ course, one has no way of knowing how \exmp{gid_t} is declared on
+ other systems. For this reason, it is preferable to use the
+ \var{MAKE_CSTRUCT_INT_FIELD} macro in cases involving integer valued
+ fields, e.g.,
+#v+
+ SLang_CStruct_Field_Type X_t_Layout [] =
+ {
+ MAKE_CSTRUCT_INT_FIELD(X_t, pid, "pid", 0),
+ MAKE_CSTRUCT_INT_FIELD(X_t, group, "group", 0),
+ SLANG_END_CSTRUCT_TABLE
+ };
+#v-
+
+ Before leaving this section, it is important to mention that
+ access to character array fields is not permitted via this
+ interface. That is, a structure such as
+#v+
+ typedef struct
+ {
+ char name[32];
+ }
+ Name_Type;
+#v-
+ is not supported since \exmp{char name[32]} is not a
+ \var{SLANG_STRING_TYPE} object. Always keep in mind that a
+ \var{SLANG_STRING_TYPE} object is a \exmp{char *}.
+
+\sect2{Intrinsic Structures}
+
+ Here we show how to make intrinsic structures available to
+ the interpreter.
+
+ The simplest interface is to structure pointers and not
+ to the actual structures themselves. The latter would require the
+ interpreter to be involved with the creation and destruction of the
+ structures. Dealing with the pointers themselves is far simpler.
+
+ As an example, consider an object such as
+#v+
+ typedef struct _Window_Type
+ {
+ char *title;
+ int row;
+ int col;
+ int width;
+ int height;
+ } Window_Type;
+#v-
+ which defines a window object with a title, size (\var{width},
+ \var{height}), and location (\var{row}, \var{col}).
+
+ We can make variables of type \var{Window_Type} available to the
+ interpreter via a table as follows:
+#v+
+ static SLang_IStruct_Field_Type Window_Type_Field_Table [] =
+ {
+ MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 1),
+ MAKE_ISTRUCT_FIELD(Window_Type, row, "row", SLANG_INT_TYPE, 0),
+ MAKE_ISTRUCT_FIELD(Window_Type, col, "col", SLANG_INT_TYPE, 0),
+ MAKE_ISTRUCT_FIELD(Window_Type, width, "width", SLANG_INT_TYPE, 0),
+ MAKE_ISTRUCT_FIELD(Window_Type, height, "height", SLANG_INT_TYPE, 0),
+ SLANG_END_ISTRUCT_TABLE
+ };
+#v-
+ More precisely, this defines the layout of the \var{Window_Type} structure.
+ Here, the \var{title} has been declared as a read-only field. Using
+#v+
+ MAKE_ISTRUCT_FIELD(Window_Type, title, "title", SLANG_STRING_TYPE, 0),
+#v-
+ would allow read-write access.
+
+ Now suppose that \var{My_Window} is a pointer to a \var{Window_Type}
+ object, i.e.,
+#v+
+ Window_Type *My_Window;
+#v-
+ We can make this variable available to the interpreter via the
+ \cfun{SLadd_istruct_table} function:
+#v+
+ if (-1 == SLadd_istruct_table (Window_Type_Field_Table,
+ (VOID_STAR) &My_Window,
+ "My_Win"))
+ exit (1);
+#v-
+ This creates a S-Lang interpreter variable called \var{My_Win} whose value
+ corresponds to the \var{My_Win} structure. This would permit one to
+ access the fields of \var{My_Window} via \slang statements such as
+#v+
+ define set_width_and_height (w,h)
+ {
+ My_Win.width = w;
+ My_Win.height = h;
+ }
+#v-
+
+ It is extremely important to understand that the interface described in
+ this section does not allow the interpreter to create new instances of
+ \var{Window_Type} objects. The interface merely defines an association or
+ correspondence between an intrinsic structure pointer and a \slang
+ variable. For example, if the value of \var{My_Window} is \var{NULL}, then
+ \var{My_Win} would also be \var{NULL}.
+
+ One should be careful in allowing read/write access to character string
+ fields. If read/write access is allowed, then the application should
+ always use the \cfun{SLang_create_slstring} and \cfun{SLang_free_slstring}
+ functions to set the character string field of the structure.
+
+#%}}}
+
+
+#%}}}
+
+#%}}}
+
+\chapter{Keyboard Interface} #%{{{
+
+#%{{{ Overview
+
+ \slang's keyboard interface has been designed to allow an
+ application to read keyboard input from the user in a
+ system-independent manner. The interface consists of a set of low
+ routines for reading single character data as well as a higher
+ level interface (\grp{SLkp}) which utilize \slang's keymap facility
+ for reading multi-character sequences.
+
+ To initialize the interface, one must first call the function
+ \verb{SLang_init_tty}. Before exiting the program, the function
+ \verb{SLang_reset_tty} must be called to restore the keyboard
+ interface to its original state. Once initialized, the low-level
+ \verb{SLang_getkey} function may be used to read \em{simgle}
+ keyboard characters from the terminal. An application using the
+ higher-level \grp{SLkp} interface will read charcters using the
+ \verb{SLkp_getkey} function.
+
+ In addition to these basic functions, there are also functions to
+ ``unget'' keyboard characters, flush the input, detect pending-input
+ with a timeout, etc. These functions are defined below.
+
+#%}}}
+
+\sect{Initializing the Keyboard Interface} #%{{{
+
+ The function \verb{SLang_init_tty} must be called to initialize the
+ terminal for single character input. This puts the terminal in a mode
+ usually referred to as ``raw'' mode.
+
+ The prototype for the function is:
+#v+
+ int SLang_init_tty (int abort_char, int flow_ctrl, int opost);
+#v-
+ It takes three parameters that are used to specify how the terminal is to
+ be initialized.
+#%+
+ Although the \slang keyboard interface has been
+ %designed to be as system independent as possible, there are semantic
+ % differences.
+#%-
+
+ The first parameter, \verb{abort_char}, is used to specify the interrupt
+ character (\tt{SIGINT}). Under MSDOS, this value corresponds to the scan
+ code of the character that will be used to generate the interrupt. For
+ example, under MSDOS, \verb{34} should be used to make \key{Ctrl-G} generate an
+ interrupt signal since 34 is the scan code for \key{G}. On other
+ systems, the value of \verb{abort_char} will simply be the ascii value of
+ the control character that will be used to generate the interrupt signal,
+ e.g., \tt{7} for \key{Ctrl-G}. If \verb{-1} is passed, the interrupt
+ character will not be changed.
+
+ Pressing the interrupt character specified by the first argument will
+ generate a signal (\tt{SIGINT}) that may or not be caught by the
+ application. It is up to the application to catch this signal. \slang
+ provides the function \verb{Slang_set_abort_signal} to make it easy to
+ facilitate this task.
+
+ The second parameter is used to specify whether or not flow control should
+ be used. If this parameter is zero, flow control is enabled otherwise
+ it is disabled. Disabling flow control is necessary to pass certain
+ characters to the application (e.g., \key{Ctrl-S} and \key{Ctrl-Q}).
+ For some systems such as MSDOS, this parameter is meaningless.
+
+ The third parameter, \verb{opost}, is used to turn output processing on or
+ off. If \verb{opost} is zero, output processing is \em{not} turned on
+ otherwise, output processing is turned on.
+
+ The \verb{SLang_init_tty} function returns -1 upon failure. In addition,
+ after it returns, the \slang global variable \verb{SLang_TT_Baud_Rate}
+ will be set to the baud rate of the terminal if this value can be
+ determined.
+
+ Example:
+#v+
+ if (-1 == SLang_init_tty (7, 0, 0)) /* For MSDOS, use 34 as scan code */
+ {
+ fprintf (stderr, "Unable to initialize the terminal.\n");
+ exit (1);
+ }
+ SLang_set_abort_signal (NULL);
+#v-
+ Here the terminal is initialized such that flow control and output
+ processing are turned off. In addition, the character
+ \key{Ctrl-G}\footnote{For MSDOS systems, use the \em{scan code} 34
+ instead of 7 for \key{Ctrl-G}} has been specified to be the interrupt
+ character. The function \verb{SLang_set_abort_signal} is used to
+ install the default \slang interrupt signal handler.
+
+#%}}}
+
+\sect{Resetting the Keyboard Interface} #%{{{
+
+ The function \verb{SLang_reset_tty} must be called to reset the terminal
+ to the state it was in before the call to \verb{SLang_init_tty}. The
+ prototype for this function is:
+#v+
+ void SLang_reset_tty (void);
+#v-
+ Usually this function is only called before the program exits. However,
+ if the program is suspended it should also be called just before suspension.
+
+#%}}}
+
+\sect{Initializing the \grp{SLkp} Routines} #%{{{
+
+ Extra initialization of the higher-level \grp{SLkp} functions are
+ required because they are layered on top of the lower level
+ routines. Since the \verb{SLkp_getkey} function is able to process
+ function and arrow keys in a terminal independent manner, it is
+ necessary to call the \verb{SLtt_get_terminfo} function to get
+ information about the escape character sequences that the terminal's
+ function keys send. Once that information is available, the
+ \verb{SLkp_init} function can construct the proper keymaps to
+ process the escape sequences.
+
+ This part of the initialization process for an application using
+ this interface will look something like:
+
+#v+
+ SLtt_get_terminfo ();
+ if (-1 == SLkp_init ())
+ {
+ SLang_doerror ("SLkp_init failed.");
+ exit (1);
+ }
+ if (-1 == SLang_init_tty (-1, 0, 1))
+ {
+ SLang_doerror ("SLang_init_tty failed.");
+ exit (1);
+ }
+#v-
+
+ It is important to check the return status of the \verb{SLkp_init}
+ function which can failed if it cannot allocate enough memory for
+ the keymap.
+
+#%}}}
+
+\sect{Setting the Interrupt Handler} #%{{{
+
+ The function \verb{SLang_set_abort_signal} may be used to associate an
+ interrupt handler with the interrupt character that was previously
+ specified by the \verb{SLang_init_tty} function call. The prototype for
+ this function is:
+#v+
+ void SLang_set_abort_signal (void (*)(int));
+#v-
+ This function returns nothing and takes a single parameter which is a
+ pointer to a function taking an integer value and returning
+ \verb{void}. If a \verb{NULL} pointer is passed, the default \slang
+ interrupt handler will be used. The \slang default interrupt handler
+ under Unix looks like:
+#v+
+ static void default_sigint (int sig)
+ {
+ SLsignal_intr (SIGINT, default_sigint);
+ SLKeyBoard_Quit = 1;
+ if (SLang_Ignore_User_Abort == 0) SLang_Error = USER_BREAK;
+ }
+#v-
+ It simply sets the global variable \verb{SLKeyBoard_Quit} to one and
+ if the variable \verb{SLang_Ignore_User_Abort} is non-zero,
+ \verb{SLang_Error} is set to indicate a user break condition. (The
+ function \verb{SLsignal_intr} is similar to the standard C
+ \verb{signal} function \em{except that it will interrupt system
+ calls}. Some may not like this behavior and may wish to call
+ this \verb{SLang_set_abort_signal} with a different handler.)
+
+ Although the function expressed above is specific to Unix, the
+ analogous routines for other operating systems are equivalent in
+ functionality even though the details of the implementation may vary
+ drastically (e.g., under MSDOS, the hardware keyboard interrupt
+ \verb{int 9h} is hooked).
+
+#%}}}
+
+\sect{Reading Keyboard Input with SLang_getkey} #%{{{
+
+ After initializing the keyboard via \verb{SLang_init_tty},
+ the \slang function \verb{SLang_getkey} may be used to read
+ characters from the terminal interface. In addition, the function
+ \verb{SLang_input_pending} may be used to determine whether or not
+ keyboard input is available to be read.
+
+ These functions have prototypes:
+#v+
+ unsigned int SLang_getkey (void);
+ int SLang_input_pending (int tsecs);
+#v-
+ The \verb{SLang_getkey} function returns a single character from the
+ terminal. Upon failure, it returns \verb{0xFFFF}. If the interrupt
+ character specified by the \verb{SLang_init_tty} function is pressed
+ while this function is called, the function will return the value of the
+ interrupt character and set the \slang global variable
+ \verb{SLKeyBoard_Quit} to a non-zero value. In addition, if the default
+ \slang interrupt handler has been specified by a \verb{NULL} argument to
+ the \verb{SLang_set_abort_signal} function, the global variable
+ \verb{SLang_Error} will be set to \verb{USER_BREAK} \em{unless} the
+ variable \verb{SLang_Ignore_User_Abort} is non-zero.
+
+ The \verb{SLang_getkey} function waits until input is available to be
+ read. The \verb{SLang_input_pending} function may be used to determine
+ whether or not input is ready. It takes a single parameter that indicates
+ the amount of time to wait for input before returning with information
+ regarding the availability of input. This parameter has units of one
+ tenth (1/10) of a second, i.e., to wait one second, the value of the
+ parameter should be \tt{10}. Passing a value of zero causes the function
+ to return right away. \verb{SLang_input_pending} returns a positive
+ integer if input is available or zero if input is not available. It will
+ return -1 if an error occurs.
+
+ Here is a simple example that reads keys from the terminal until one
+ presses \key{Ctrl-G} or until 5 seconds have gone by with no input:
+#v+
+ #include <stdio.h>
+ #include "slang.h"
+ int main ()
+ {
+ int abort_char = 7; /* For MSDOS, use 34 as scan code */
+ unsigned int ch;
+
+ if (-1 == SLang_init_tty (abort_char, 0, 1))
+ {
+ fprintf (stderr, "Unable to initialize the terminal.\n");
+ exit (-1);
+ }
+ SLang_set_abort_signal (NULL);
+ while (1)
+ {
+ fputs ("\nPress any key. To quit, press Ctrl-G: ", stdout);
+ fflush (stdout);
+ if (SLang_input_pending (50) == 0) /* 50/10 seconds */
+ {
+ fputs ("Waited too long! Bye\n", stdout);
+ break;
+ }
+
+ ch = SLang_getkey ();
+ if (SLang_Error == USER_BREAK)
+ {
+ fputs ("Ctrl-G pressed! Bye\n", stdout);
+ break;
+ }
+ putc ((int) ch, stdout);
+ }
+ SLang_reset_tty ();
+ return 0;
+ }
+#v-
+
+
+#%}}}
+
+\sect{Reading Keyboard Input with SLkp_getkey} #%{{{
+
+ Unlike the low-level function \verb{SLang_getkey}, the
+ \verb{SLkp_getkey} function can read a multi-character sequence
+ associated with function keys. The \verb{SLkp_getkey} function uses
+ \verb{SLang_getkey} and \slang's keymap facility to process escape
+ sequences. It returns a single integer which describes the key that
+ was pressed:
+#v+
+ int SLkp_getkey (void);
+#v-
+ That is, the \verb{SLkp_getkey} function simple provides a mapping
+ between keys and integers. In this context the integers are called
+ \em{keysyms}.
+
+ For single character input such as generated by the \key{a} key on
+ the keyboard, the function returns the character that was generated,
+ e.g., \verb{'a'}. For single characters, \verb{SLkp_getkey} will
+ always return an keysym whose value ranges from 0 to 256. For
+ keys that generate multiple character sequences, e.g., a function or
+ arrow key, the function returns an keysym whose value is greater
+ that 256. The actual values of these keysyms are represented as
+ macros defined in the \file{slang.h} include file. For example, the
+ up arrow key corresponds to the keysym whose value is
+ \verb{SL_KEY_UP}.
+
+ Since it is possible for the user to enter a character sequence that
+ does not correspond to any key. If this happens, the special keysym
+ \verb{SL_KEY_ERR} will be returned.
+
+ Here is an example of how \verb{SLkp_getkey} may be used by a file
+ viewer:
+#v+
+ switch (SLkp_getkey ())
+ {
+ case ' ':
+ case SL_KEY_NPAGE:
+ next_page ();
+ break;
+ case 'b':
+ case SL_KEY_PPAGE:
+ previous_page ();
+ break;
+ case '\r':
+ case SL_KEY_DOWN:
+ next_line ();
+ break;
+ .
+ .
+ case SL_KEY_ERR:
+ default:
+ SLtt_beep ();
+ }
+#v-
+
+ Unlike its lower-level counterpart, \verb{SLang_getkey}, there do
+ not yet exist any functions in the library that are capable of
+ ``ungetting'' keysyms. In particular, the \verb{SLang_ungetkey}
+ function will not work.
+
+#%}}}
+
+\sect{Buffering Input} #%{{{
+
+ \slang has several functions pushing characters back onto the
+ input stream to be read again later by \verb{SLang_getkey}. It
+ should be noted that none of the above functions are designed to
+ push back keysyms read by the \verb{SLkp_getkey} function. These
+ functions are declared as follows:
+#v+
+ void SLang_ungetkey (unsigned char ch);
+ void SLang_ungetkey_string (unsigned char *buf, int buflen);
+ void SLang_buffer_keystring (unsigned char *buf, int buflen);
+#v-
+
+ \verb{SLang_ungetkey} is the most simple of the three functions. It takes
+ a single character a pushes it back on to the input stream. The next call to
+ \verb{SLang_getkey} will return this character. This function may be used
+ to \em{peek} at the character to be read by first reading it and then
+ putting it back.
+
+ \verb{SLang_ungetkey_string} has the same function as
+ \verb{SLang_ungetkey} except that it is able to push more than one
+ character back onto the input stream. Since this function can push back
+ null (ascii 0) characters, the number of characters to push is required as
+ one of the parameters.
+
+ The last of these three functions, \verb{SLang_buffer_keystring} can
+ handle more than one charater but unlike the other two, it places the
+ characters at the \em{end} of the keyboard buffer instead of at the
+ beginning.
+
+ Note that the use of each of these three functions will cause
+ \verb{SLang_input_pending} to return right away with a non-zero value.
+
+ Finally, the \slang keyboard interface includes the function
+ \verb{SLang_flush_input} with prototype
+#v+
+ void SLang_flush_input (void);
+#v-
+ It may be used to discard \em{all} input.
+
+ Here is a simple example that looks to see what the next key to be read is
+ if one is available:
+#v+
+ int peek_key ()
+ {
+ int ch;
+ if (SLang_input_pending (0) == 0) return -1;
+ ch = SLang_getkey ();
+ SLang_ungetkey (ch);
+ return ch;
+ }
+#v-
+
+
+#%}}}
+
+\sect{Global Variables} #%{{{
+ Although the following \slang global variables have already been
+ mentioned earlier, they are gathered together here for completeness.
+
+ \verb{int SLang_Ignore_User_Abort;}
+ If non-zero, pressing the interrupt character will not result in
+ \verb{SLang_Error} being set to \verb{USER_BREAK}.
+
+ \verb{volatile int SLKeyBoard_Quit;}
+ This variable is set to a non-zero value when the interrupt
+ character is pressed. If the interrupt character is pressed when
+ \verb{SLang_getkey} is called, the interrupt character will be
+ returned from \verb{SLang_getkey}.
+
+ \verb{int SLang_TT_Baud_Rate;}
+ On systems which support it, this variable is set to the value of the
+ terminal's baud rate after the call to \verb{SLang_init_tty}.
+
+#%}}}
+
+#%}}}
+
+\chapter{Screen Management} #%{{{
+
+ The \slang library provides two interfaces to terminal independent
+ routines for manipulating the display on a terminal. The highest level
+ interface, known as the \verb{SLsmg} interface is discussed in this
+ section. It provides high level screen management functions more
+ manipulating the display in an optimal manner and is similar in spirit to
+ the \verb{curses} library. The lowest level interface, or the
+ \verb{SLtt}
+ interface, is used by the \verb{SLsmg} routines to actually perform the
+ task of writing to the display. This interface is discussed in another
+ section. Like the keyboard routines, the \verb{SLsmg} routines are
+ \em{platform independent} and work the same on MSDOS, OS/2, Unix, and VMS.
+
+ The screen management, or \verb{SLsmg}, routines are initialized by
+ function \verb{SLsmg_init_smg}. Once initialized, the application uses
+ various \verb{SLsmg} functions to write to a \em{virtual} display. This does
+ not cause the \em{physical} terminal display to be updated immediately.
+ The physical display is updated to look like the virtual display only
+ after a call to the function \verb{SLsmg_refresh}. Before exiting, the
+ application using these routines is required to call
+ \verb{SLsmg_reset_smg} to reset the display system.
+
+ The following subsections explore \slang's screen management system in
+ greater detail.
+
+\sect{Initialization}
+
+ The function \verb{SLsmg_init_smg} must be called before any other
+ \verb{SLsmg} function can be used. It has the simple prototype:
+#v+
+ int SLsmg_init_smg (void);
+#v-
+ It returns zero if successful or -1 if it cannot allocate space for
+ the virtual display.
+
+ For this routine to properly initialize the virtual display, the
+ capabilities of the terminal must be known as well as the size of
+ the \em{physical} display. For these reasons, the lower level \verb{SLtt} routines
+ come into play. In particular, before the first call to
+ \verb{SLsmg_init_smg}, the application is required to call the function
+ \verb{SLtt_get_terminfo} before calling \verb{SLsmg_init_smg}.
+
+ The \verb{SLtt_get_terminfo} function sets the global variables
+ \verb{SLtt_Screen_Rows} and \verb{SLtt_Screen_Cols} to the values
+ appropriate for the terminal. It does this by calling the
+ \verb{SLtt_get_screen_size} function to query the terminal driver
+ for the appropriate values for these variables. From this point on,
+ it is up to the application to maintain the correct values for these
+ variables by calling the \verb{SLtt_get_screen_size} function
+ whenever the display size changes, e.g., in response to a
+ \verb{SIGWINCH} signal. Finally, if the application is going to read
+ characters from the keyboard, it is also a good idea to initialize
+ the keyboard routines at this point as well.
+
+\sect{Resetting SLsmg}
+
+ Before the program exits or suspends, the function
+ \verb{SLsmg_reset_tty}
+ should be called to shutdown the display system. This function has the
+ prototype
+#v+
+ void SLsmg_reset_smg (void);
+#v-
+ This will deallocate any memory allocated for the virtual screen and
+ reset the terminal's display.
+
+ Basically, a program that uses the \verb{SLsmg} screen management functions
+ and \slang's keyboard interface will look something like:
+#v+
+ #include "slang.h"
+ int main ()
+ {
+ SLtt_get_terminfo ();
+ SLang_init_tty (-1, 0, 0);
+ SLsmg_init_smg ();
+
+ /* do stuff .... */
+
+ SLsmg_reset_smg ();
+ SLang_reset_tty ();
+ return 0;
+ }
+#v-
+ If this program is compiled and run, all it will do is clear the screen
+ and position the cursor at the bottom of the display. In the following
+ sections, other \verb{SLsmg} functions will be introduced which may be used
+ to make this simple program do much more.
+
+\sect{Handling Screen Resize Events}
+ The function \verb{SLsmg_reinit_smg} is designed to be used in
+ conjunction with resize events.
+
+ Under Unix-like operating systems, when the size of the display
+ changes, the application will be sent a \verb{SIGWINCH} signal. To
+ properly handle this signal, the \verb{SLsmg} routines must be
+ reinitialized to use the new display size. This may be accomplished
+ by calling \verb{SLtt_get_screen_size} to get the new size, followed by
+ \verb{SLsmg_reinit_smg} to reinitialize the \verb{SLsmg} interface
+ to use the new size. Keep in mind that these routines should
+ not be called from within the signal handler. The following code
+ illustrates the main ideas involved in handling such events:
+#v+
+ static volatile int Screen_Size_Changed;
+ static sigwinch_handler (int sig)
+ {
+ Screen_Size_Changed = 1;
+ SLsignal (SIGWINCH, sigwinch_handler);
+ }
+
+ int main (int argc, char **argv)
+ {
+ SLsignal (SIGWINCH, sigwinch_handler);
+ SLsmg_init_smg ();
+ .
+ .
+ /* Now enter main loop */
+ while (not_done)
+ {
+ if (Screen_Size_Changed)
+ {
+ SLtt_get_screen_size ();
+ SLsmg_reinit_smg ();
+ redraw_display ();
+ }
+ .
+ .
+ }
+ return 0;
+ }
+#v-
+
+
+\sect{SLsmg Functions} #%{{{
+
+ In the previous sections, functions for initializing and shutting down the
+ \verb{SLsmg} routines were discussed. In this section, the rest of the
+ \verb{SLsmg} functions are presented. These functions act only on the
+ \em{virtual} display. The \em{physical} display is updated when the
+ \verb{SLsmg_refresh} function is called and \em{not until that time}.
+ This function has the simple prototype:
+#v+
+ void SLsmg_refresh (void);
+#v-
+
+\sect1{Positioning the cursor}
+
+ The \verb{SLsmg_gotorc} function is used to position the cursor at a given
+ row and column. The prototype for this function is:
+#v+
+ void SLsmg_gotorc (int row, int col);
+#v-
+ The origin of the screen is at the top left corner and is given the
+ coordinate (0, 0), i.e., the top row of the screen corresponds to
+ \verb{row = 0} and the first column corresponds to \verb{col = 0}. The last
+ row of the screen is given by \verb{row = SLtt_Screen_Rows - 1}.
+
+ It is possible to change the origin of the coordinate system by using the
+ function \verb{SLsmg_set_screen_start} with prototype:
+#v+
+ void SLsmg_set_screen_start (int *r, int *c);
+#v-
+ This function takes pointers to the new values of the first row and first
+ column. It returns the previous values by modifying the values of the
+ integers at the addresses specified by the parameter list. A
+ \verb{NULL}
+ pointer may be passed to indicate that the origin is to be set to its
+ initial value of 0. For example,
+#v+
+ int r = 10;
+ SLsmg_set_screen_start (&r, NULL);
+#v-
+ sets the origin to (10, 0) and after the function returns, the variable
+ \verb{r} will have the value of the previous row origin.
+
+\sect1{Writing to the Display}
+
+ \verb{SLsmg} has several routines for outputting text to the virtual
+ display. The following points should be understood:
+\begin{itemize}
+\item The text is output at the position of the cursor of the virtual
+ display and the cursor is advanced to the position that corresponds to
+ the end of the text.
+
+\item Text does \em{not} wrap at the boundary of the
+ display--- it is trucated. This behavior seems to be more useful in
+ practice since most programs that would use screen management tend to
+ be line oriented.
+
+\item Control characters are displayed in a two character sequence
+ representation with \verb{^} as the first character. That is,
+ \key{Ctrl-X} is output as \verb{^X}.
+
+\item The newline character does \em{not} cause the cursor to advance to
+ the next row. Instead, when a newline character is encountered when
+ outputting text, the output routine will return. That is, outputting
+ a string containing a newline character will only display the contents
+ of the string up to the newline character.
+\end{itemize}
+
+ Although the some of the above items might appear to be too restrictive, in
+ practice this is not seem to be the case. In fact, the design of the
+ output routines was influenced by their actual use and modified to
+ simplify the code of the application utilizing them.
+
+ \verb{void SLsmg_write_char (char ch);}
+ Write a single character to the virtual display.
+
+ \verb{void SLsmg_write_nchars (char *str, int len);}
+ Write \verb{len} characters pointed to by \verb{str} to the virtual display.
+
+ \verb{void SLsmg_write_string (char *str);}
+ Write the null terminated string given by pointer \verb{str} to the virtual
+ display. This function is a wrapper around \verb{SLsmg_write_nchars}.
+
+ \verb{void SLsmg_write_nstring (char *str, int n);}
+ Write the null terminated string given by pointer \verb{str} to the virtual
+ display. At most, only \verb{n} characters are written. If the length of
+ the string is less than \verb{n}, then the string will be padded with blanks.
+ This function is a wrapper around \verb{SLsmg_write_nchars}.
+
+ \verb{void SLsmg_printf (char *fmt, ...);}
+ This function is similar to \verb{printf} except that it writes to the
+ \verb{SLsmg} virtual display.
+
+ \verb{void SLsmg_vprintf (char *, va_list);}
+ Like \verb{SLsmg_printf} but uses a variable argument list.
+
+\sect1{Erasing the Display}
+
+ The following functions may be used to fill portions of the display with
+ blank characters. The attributes of blank character are the current
+ attributes. (See below for a discussion of character attributes)
+
+ \verb{void SLsmg_erase_eol (void);}
+ Erase line from current position to the end of the line.
+
+ \verb{void SLsmg_erase_eos (void);}
+ Erase from the current position to the end of the screen.
+
+ \verb{void SLsmg_cls (void);}
+ Clear the entire virtual display.
+
+\sect1{Setting Character Attributes}
+
+ Character attributes define the visual characteristics the character
+ possesses when it is displayed. Visual characteristics include the
+ foreground and background colors as well as other attributes such as
+ blinking, bold, and so on. Since \verb{SLsmg} takes a different approach
+ to this problem than other screen management libraries an explanation of
+ this approach is given here. This approach has been motivated by
+ experience with programs that require some sort of screen management.
+
+ Most programs that use \verb{SLsmg} are composed of specific textual
+ objects or objects made up of line drawing characters. For example,
+ consider an application with a menu bar with drop down menus. The menus
+ might be enclosed by some sort of frame or perhaps a shadow. The basic
+ idea is to associate an integer to each of the objects (e.g., menu bar,
+ shadow, current menu item, etc.) and create a mapping from the integer to
+ the set of attributes. In the terminology of \verb{SLsmg}, the integer is
+ simply called an \em{object}.
+
+ For example, the menu bar might be associated with the object \verb{1}, the
+ drop down menu could be object \verb{2}, the shadow could be object
+ \verb{3},
+ and so on.
+
+ The range of values for the object integer is restricted from 0 up to
+ and including 255 on all systems except MSDOS where the maximum allowed
+ integer is 15\footnote{This difference is due to memory constraints
+ imposed by MSDOS. This restriction might be removed in a future version of
+ the library.}. The object numbered zero should not be regarding as an
+ object at all. Rather it should be regarded as all \em{other} objects
+ that have not explicitly been given an object number. \verb{SLsmg}, or
+ more precisely \verb{SLtt}, refers to the attributes of this special object
+ as the \em{default} or \em{normal} attributes.
+
+ The \verb{SLsmg} routines know nothing about the mapping of the color to the
+ attributes associated with the color. The actual mapping takes place at a
+ lower level in the \verb{SLtt} routines. Hence, to map an object to the
+ actual set of attributes requires a call to any of the following
+ \verb{SLtt}
+ routines:
+#v+
+ void SLtt_set_color (int obj, char *name, char *fg, char *bg);
+ void SLtt_set_color_object (int obj, SLtt_Char_Type attr);
+ void SLtt_set_mono (int obj, char *, SLtt_Char_Type attr);
+#v-
+ Only the first of these routines will be discussed briefly here. The
+ latter two functions allow more fine control over the object to attribute
+ mapping (such as assigning a ``blink'' attribute to the object). For a
+ more full explanation on all of these routines see the section about the
+ \verb{SLtt} interface.
+
+ The \verb{SLtt_set_color} function takes four parameters. The first
+ parameter, \verb{obj}, is simply the integer of the object for which
+ attributes are to be assigned. The second parameter is currently
+ unused by these routines. The third and forth parameters, \verb{fg}
+ and \verb{bg}, are the names of the foreground and background color
+ to be used associated with the object. The strings that one can use
+ for the third and fourth parameters can be any one of the 16 colors:
+#v+
+ "black" "gray"
+ "red" "brightred"
+ "green" "brightgreen"
+ "brown" "yellow"
+ "blue" "brightblue"
+ "magenta" "brightmagenta"
+ "cyan" "brightcyan"
+ "lightgray" "white"
+#v-
+ The value of the foreground parameter \verb{fg} can be anyone of these
+ sixteen colors. However, on most terminals, the background color will
+ can only be one of the colors listed in the first column\footnote{This is
+ also true on the Linux console. However, it need not be the case and
+ hopefully the designers of Linux will someday remove this restriction.}.
+
+ Of course not all terminals are color terminals. If the \slang global
+ variable \verb{SLtt_Use_Ansi_Colors} is non-zero, the terminal is
+ assumed to be a color terminal. The \verb{SLtt_get_terminfo} will
+ try to determine whether or not the terminal supports colors and set
+ this variable accordingly. It does this by looking for the
+ capability in the terminfo/termcap database. Unfortunately many Unix
+ databases lack this information and so the \verb{SLtt_get_terminfo}
+ routine will check whether or not the environment variable
+ \verb{COLORTERM} exists. If it exists, the terminal will be assumed
+ to support ANSI colors and \verb{SLtt_Use_Ansi_Colors} will be set to one.
+ Nevertheless, the application should provide some other mechanism to set
+ this variable, e.g., via a command line parameter.
+
+ When the \verb{SLtt_Use_Ansi_Colors} variable is zero, all objects
+ with numbers greater than one will be displayed in inverse
+ video\footnote{This behavior can be modified by using the
+ \tt{SLtt_set_mono} function call.}.
+
+ With this background, the \verb{SLsmg} functions for setting the character
+ attributes can now be defined. These functions simply set the object
+ attributes that are to be assigned to \em{subsequent} characters written
+ to the virtual display. For this reason, the new attribute is called the
+ \em{current} attribute.
+
+ \verb{void SLsmg_set_color (int obj);}
+ Set the current attribute to those of object \verb{obj}.
+
+ \verb{void SLsmg_normal_video (void);}
+ This function is equivalent to \verb{SLsmg_set_color (0)}.
+
+ \verb{void SLsmg_reverse_video (void);}
+ This function is equivalent to \verb{SLsmg_set_color (1)}. On monochrome
+ terminals, it is equivalent to setting the subsequent character attributes
+ to inverse video.
+
+ Unfortunately there does not seem to be a standard way for the
+ application or, in particular, the library to determine which color
+ will be used by the terminal for the default background. Such
+ information would be useful in initializing the foreground and
+ background colors associated with the default color object (0). FOr
+ this reason, it is up to the application to provide some means for
+ the user to indicate what these colors are for the particular
+ terminal setup. To facilitate this, the \verb{SLtt_get_terminfo}
+ function checks for the existence of the \verb{COLORFGBG}
+ environment variable. If this variable exists, its value will be
+ used to initialize the colors associated with the default color
+ object. Specifically, the value is assumed to consist of a
+ foreground color name and a background color name separated by a
+ semicolon. For example, if the value of \verb{COLORTERM} is
+ \verb{lightgray;blue}, the default color object will be initialized
+ to represent a \verb{lightgray} foreground upon a \verb{blue}
+ background.
+
+\sect1{Lines and Alternate Character Sets}
+ The \slang screen management library also includes routines for turning
+ on and turning off alternate character sets. This is especially useful
+ for drawing horizontal and vertical lines.
+
+ \verb{void SLsmg_set_char_set (int flag);}
+ If \verb{flag} is non-zero, subsequent write functions will use characters
+ from the alternate character set. If \verb{flag} is zero, the default, or,
+ ordinary character set will be used.
+
+ \verb{void SLsmg_draw_hline (int len);}
+ Draw a horizontal line from the current position to the column that is
+ \verb{len} characters to the right.
+
+ \verb{void SLsmg_draw_vline (int len);}
+ Draw a horizontal line from the current position to the row that is
+ \verb{len} rows below.
+
+ \verb{void SLsmg_draw_box (int r, int c, int dr, int dc);}
+ Draw a box whose upper right corner is at row \verb{r} and column
+ \verb{c}.
+ The box spans \verb{dr} rows and \verb{dc} columns. The current position
+ will be left at row \verb{r} and column \verb{c}.
+
+\sect1{Miscellaneous Functions}
+
+ \verb{void SLsmg_touch_lines (int r, int n);}
+ Mark screen rows numbered \verb{r}, \verb{r + 1}, \ldots \verb{r +
+ (n - 1)} as
+ modified. When \verb{SLsmg_refresh} is called, these rows will be
+ completely redrawn.
+
+ \verb{unsigned short SLsmg_char_at(void);}
+ Returns the character and its attributes object number at the current
+ cursor position. The character itself occupies the lower byte and the
+ object attributes number forms the upper byte. The object returned
+ by this function call should not be written back out via any of the
+ functions that write characters or character strings.
+
+
+#%}}}
+
+\sect{Variables} #%{{{
+
+ The following \slang global variables are used by the \verb{SLsmg}
+ interface. Some of these have been previously discussed.
+
+ \verb{int SLtt_Screen_Rows;}
+ \verb{int SLtt_Screen_Cols;}
+ The number of rows and columns of the \em{physical} display. If either of
+ these numbers changes, the functions \verb{SLsmg_reset_smg} and
+ \verb{SLsmg_init_smg} should be called again so that the \verb{SLsmg}
+ routines can re-adjust to the new size.
+
+ \verb{int SLsmg_Tab_Width;}
+ Set this variable to the tab width that will be used when expanding tab
+ characters. The default is 8.
+
+ \verb{int SLsmg_Display_Eight_Bit}
+ This variable determines how characters with the high bit set are to be
+ output. Specifically, a character with the high bit set with a value
+ greater than or equal to this value is output as is; otherwise, it will be
+ output in a 7-bit representation. The default value for this variable is
+ \verb{128} for MSDOS and \verb{160} for other systems (ISO-Latin).
+
+ \verb{int SLtt_Use_Ansi_Colors;}
+ If this value is non-zero, the terminal is assumed to support ANSI colors
+ otherwise it is assumed to be monochrome. The default is 0.
+
+ \verb{int SLtt_Term_Cannot_Scroll;}
+ If this value is zero, the \verb{SLsmg} will attempt to scroll the physical
+ display to optimize the update. If it is non-zero, the screen management
+ routines will not perform this optimization. For some applications, this
+ variable should be set to zero. The default value is set by the
+ \verb{SLtt_get_terminfo} function.
+
+#%}}}
+
+\sect{Hints for using SLsmg}
+
+ This section discusses some general design issues that one must face when
+ writing an application that requires some sort of screen management.
+
+#%}}}
+
+\chapter{Signal Functions} #%{{{
+
+ Almost all non-trivial programs must worry about signals. This is
+ especially true for programs that use the \slang terminal
+ input/output and screen management routines. Unfortunately, there is
+ no fixed way to handle signals; otherwise, the Unix kernel would take
+ care of all issues regarding signals and the application programmer
+ would never have to worry about them. For this reason, none of the
+ routines in the \slang library catch signals; however, some of the
+ routines block the delivery of signals during crucial moments. It is
+ up to the application programmer to install handlers for the various
+ signals of interest.
+
+ For the interpreter, the most important signal to worry about is
+ \var{SIGINT}. This signal is usually generated when the user presses
+ \key{Ctrl-C} at the keyboard. The interpreter checks the value of the
+ \var{SLang_Error} variable to determine whether or not it should abort the
+ interpreting process and return control back to the application.
+ This means that if \var{SIGINT} is to be used to abort the interpreter, a
+ signal handler for \var{SIGINT} should be installed. The handler should
+ set the value of \var{SLang_Error} to \var{SL_USER_BREAK}.
+
+ Applications that use the \grp{tty} \var{getkey} routines or the screen
+ management routines must worry about signals such as:
+#v+
+ SIGINT interrupt
+ SIGTSTP stop
+ SIGQUIT quit
+ SIGTTOU background write
+ SIGTTIN background read
+ SIGWINCH window resize
+#v-
+ It is important that handlers be established for these signals while
+ the either the \var{SLsmg} routines or the \var{getkey} routines are
+ initialized. The \cfun{SLang_init_tty}, \cfun{SLang_reset_tty},
+ \cfun{SLsmg_init_smg}, and \cfun{SLsmg_reset_smg} functions block these
+ signals from occuring while they are being called.
+
+ Since a signal can be delivered at any time, it is important for the
+ signal handler to call only functions that can be called from a
+ signal handler. This usually means that such function must be
+ re-entrant. In particular, the \var{SLsmg} routines are \em{not}
+ re-entrant; hence, they should not be called when a signal is being
+ processed unless the application can ensure that the signal was not
+ delivered while an \var{SLsmg} function was called. This statement
+ applies to many other functions such as \var{malloc}, or, more
+ generally, any function that calls \var{malloc}. The upshot is that
+ the signal handler should not attempt to do too much except set a
+ global variable for the application to look at while not in a signal
+ handler.
+
+ The \slang library provides two functions for blocking and unblocking the
+ above signals:
+#v+
+ int SLsig_block_signals (void);
+ int SLsig_unblock_signals (void);
+#v-
+ It should be noted that for every call to \cfun{SLsig_block_signals}, a
+ corresponding call should be made to \cfun{SLsig_unblock_signals}, e.g.,
+#v+
+ void update_screen ()
+ {
+ SLsig_block_signals ();
+
+ /* Call SLsmg functions */
+ .
+ .
+ SLsig_unblock_signals ();
+ }
+#v-
+ See \file{demo/pager.c} for examples.
+
+
+#%}}}
+
+\chapter{Searching Functions} #%{{{
+
+ The S-Lang library incorporates two types of searches: Regular expression
+ pattern matching and ordinary searching.
+
+\sect{Regular Expressions} #%{{{
+
+ !!! No documentation available yet !!!
+
+#%}}}
+
+\sect{Simple Searches} #%{{{
+ The routines for ordinary searching are defined in the
+ \verb{slsearch.c} file.
+ To use these routines, simply include "slang.h" in your program and simply
+ call the appropriate routines.
+
+ The searches can go in either a forward or backward direction and can
+ either be case or case insensitive. The region that is searched may
+ contain null characters (ASCII 0) however, the search string cannot in the
+ current implementation. In addition the length of the string to be found
+ is currently limited to 256 characters.
+
+ Before searching, the function \verb{SLsearch_init} must first be called to
+ \verb{`preprocess}' the search string.
+
+#%}}}
+
+\sect{Initialization} #%{{{
+ The function \verb{SLsearch_init} must be called before a search can take place.
+ Its prototype is:
+#v+
+ int SLsearch_init (char *key, int dir, int case_sens, SLsearch_Type *st);
+#v-
+ Here \verb{key} is the string to be searched for. \verb{dir} specifies the direction
+ of the search: a value greater than zero is used for searching forward and
+ a value less than zero is used for searching backward. The parameter
+ \verb{case_sens} specifies whether the search is case sensitive or not. A
+ non-zero value indicates that case is important. \verb{st} is a pointer to a
+ structure of type \verb{SLsearch_Type} defined in "slang.h". This structure is
+ initialized by this routine and must be passed to \verb{SLsearch} when the
+ search is actually performed.
+
+ This routine returns the length of the string to be searched for.
+
+#%}}}
+
+\sect{SLsearch} #%{{{
+
+#v+
+ Prototype: unsigned char *SLsearch (unsigned char *pmin,
+ unsigned char *pmax,
+ SLsearch_Type *st);
+#v-
+
+ This function performs the search defined by a previous call to
+ \verb{SLsearch_init} over a region specified by the pointers
+ \verb{pmin} and \verb{pmax}.
+
+ It returns a pointer to the start of the match if successful or it will
+ return \verb{NULL} if a match was not found.
+
+
+#%}}}
+
+#%}}}
+
+\appendix
+
+#i copyright.tm
+
+\end{\documentstyle}
diff --git a/libslang/doc/tm/fixtex.sl b/libslang/doc/tm/fixtex.sl
new file mode 100644
index 0000000..787eb91
--- /dev/null
+++ b/libslang/doc/tm/fixtex.sl
@@ -0,0 +1,56 @@
+!if (is_defined ("__argv"))
+{
+ message ("You need a newer version of jed to run this script");
+ quit_jed ();
+}
+
+if (__argc != 4)
+{
+ message ("Usage: jed -script fixtex.sl <filename>");
+ quit_jed ();
+}
+
+variable file = __argv[3];
+() = read_file (file);
+
+% Patch up the >,< signs
+bob ();
+replace ("$<$", "<");
+replace ("$>$", ">");
+
+% It appears that sgml2tex screws up _for in section titles, producing \_{for}.
+replace ("ion\\_{", "ion{\\_");
+
+% Make the first chapter a preface
+bob ();
+if (bol_fsearch ("\\chapter{Preface}"))
+{
+ push_spot ();
+ push_mark ();
+ go_right (8); insert ("*"); % \chapter{ --> \chapter*{
+ () = bol_fsearch ("\\chapter{");
+ push_spot ();
+
+ insert("\\tableofcontents\n");
+ eol ();
+ insert ("\n\\pagenumbering{arabic}");
+
+ pop_spot ();
+ narrow ();
+ bob ();
+ replace ("\\section{", "\\section*{");
+ widen ();
+
+ if (bol_bsearch ("\\tableofcontents"))
+ delete_line ();
+
+ pop_spot ();
+ if (bol_bsearch ("\\maketitle"))
+ insert ("\\pagenumbering{roman}\n");
+
+}
+
+save_buffer ();
+quit_jed ();
+
+
diff --git a/libslang/doc/tm/preface.tm b/libslang/doc/tm/preface.tm
new file mode 100644
index 0000000..f5d9caa
--- /dev/null
+++ b/libslang/doc/tm/preface.tm
@@ -0,0 +1,95 @@
+
+\chapter{Preface} #%{{{
+
+ \slang is an interpreted language that was designed from the start
+ to be easily embedded into a program to provide it with a powerful
+ extension language. Examples of programs that use \slang as an
+ extension language include the \jed text editor, the \slrn
+ newsreader, and \sldxe (unreleased), a numerical computation
+ program. For this reason, \slang does not exist as a separate
+ application and many of the examples in this document are presented
+ in the context of one of the above applications.
+
+ \slang is also a programmer's library that permits a programmer to
+ develop sophisticated platform-independent software. In addition to
+ providing the \slang extension language, the library provides
+ facilities for screen management, keymaps, low-level terminal I/O,
+ etc. However, this document is concerned only with the extension
+ language and does not address these other features of the \slang
+ library. For information about the other components of the library,
+ the reader is referred to the \slang-library-reference.
+
+\sect{A Brief History of \slang} #%{{{
+
+ I first began working on \slang sometime during the fall of 1992.
+ At that time I was writing a text editor (\jed), which I wanted to
+ endow with a macro language. It occured to me that an
+ application-independent language that could be embedded into the
+ editor would prove more useful because I could envision embedding it
+ into other programs. As a result, \slang was born.
+
+ \slang was originally a stack language that supported a
+ postscript-like syntax. For that reason, I named it \slang, where
+ the \em{S} was supposed to emphasize its stack-based nature. About
+ a year later, I began to work on a preparser that would allow one to
+ write using a more traditional infix syntax making it easier to use
+ for those unfamiliar with stack based languages. Currently, the
+ syntax of the language resembles C, nevertheless some
+ postscript-like features still remain, e.g., the `\var{%}' character
+ is still used as a comment delimiter.
+
+#%}}}
+
+\sect{Acknowledgements} #%{{{
+
+ Since I first released \slang, I have received a lot feedback about
+ the library and the language from many people. This has given me
+ the opportunity and pleasure to interact with several people to
+ make the library portable and easy to use. In particular, I would
+ like to thank the following individuals:
+
+ Luchesar Ionkov \tt{<lionkov@sf.cit.bg>} for his comments and
+ criticisms of the syntax of the language. He was the person who
+ made me realize that the low-level byte-code engine should be
+ totally type-independent. He also improved the tokenizer and
+ preparser and impressed upon me that the language needed a
+ grammar.
+
+ Mark Olesen \tt{<olesen@weber.me.queensu.ca>} for his many patches to
+ various aspects of the library and his support on AIX. He also
+ contributed a lot to the pre-processing (\var{SLprep}) routines.
+
+ John Burnell \tt{<j.burnell@irl.cri.nz>} for the OS/2 port of the
+ video and keyboard routines. He also made value suggestions
+ regarding the interpreter interface.
+
+ Darrel Hankerson \tt{<hankedr@mail.auburn.edu>} for cleaning up and
+ unifying some of the code and the makefiles.
+
+ Dominik Wujastyk \tt{<ucgadkw@ucl.ac.uk>} who was always willing to test
+ new releases of the library.
+
+ Michael Elkins \tt{<me@muddcs.cs.hmc.edu>} for his work on the curses
+ emulation.
+
+ Ulli Horlacher \tt{<framstag@belwue.de>} and Oezguer Kesim
+ \tt{<kesim@math.fu-berlin.de>} for the \slang newsgroup and mailing list.
+
+ Hunter Goatley, Andy Harper \tt{<Andy.Harper@kcl.ac.uk>}, and Martin
+ P.J. Zinser \tt{<zinser@decus.decus.de>} for their VMS support.
+
+ Dave Sims \tt{<sims@usa.acsys.com>} and Chin Huang
+ \tt{<cthuang@vex.net>} for Windows 95 and Windows NT support.
+
+ Lloyd Zusman \tt{<ljz@asfast.com>} and Rich Roth \tt{<rich@on-the-net.com>}
+ for creating and maintaining \tt{www.s-lang.org}.
+
+ I am also grateful to many other people who send in bug-reports and
+ bug-fixes, for without such community involvement, \slang would not
+ be as well-tested and stable as it is. Finally, I would like to
+ thank my wife for her support and understanding while I spent long
+ weekend hours developing the library.
+
+#%}}}
+
+#%}}}
diff --git a/libslang/doc/tm/regexp.tm b/libslang/doc/tm/regexp.tm
new file mode 100644
index 0000000..7874b49
--- /dev/null
+++ b/libslang/doc/tm/regexp.tm
@@ -0,0 +1,98 @@
+\chapter{Regular Expressions}
+
+ The S-Lang library includes a regular expression (RE) package that
+ may be used by an application embedding the library. The RE syntax
+ should be familiar to anyone acquainted with regular expressions. In
+ this section the syntax of the \slang regular expressions is
+ discussed.
+
+\sect{\slang RE Syntax}
+
+ A regular expression specifies a pattern to be matched against a
+ string, and has the property that the contcatenation of two REs is
+ also a RE.
+
+ The \slang library supports the following standard regular
+ expressions:
+#v+
+ . match any character except newline
+ * matches zero or more occurences of previous RE
+ + matches one or more occurences of previous RE
+ ? matches zero or one occurence of previous RE
+ ^ matches beginning of a line
+ $ matches end of line
+ [ ... ] matches any single character between brackets.
+ For example, [-02468] matches `-' or any even digit.
+ and [-0-9a-z] matches `-' and any digit between 0 and 9
+ as well as letters a through z.
+ \< Match the beginning of a word.
+ \> Match the end of a word.
+ \( ... \)
+ \1, \2, ..., \9 Matches the match specified by nth \( ... \)
+ expression.
+#v-
+ In addition the following extensions are also supported:
+#v+
+ \c turn on case-sensitivity (default)
+ \C turn off case-sensitivity
+ \d match any digit
+ \e match ESC char
+#v-
+Here are some simple examples:
+
+ \exmp{"^int "} matches the \exmp{"int "} at the beginning of a line.
+
+ \exmp{"\\<money\\>"} matches \exmp{"money"} but only if it appears
+ as a separate word.
+
+ \exmp{"^$"} matches an empty line.
+
+ A more complex pattern is
+#v+
+ "\(\<[a-zA-Z]+\>\)[ ]+\1\>"
+#v-
+ which matches any word repeated consecutively. Note how the grouping
+ operators \exmp{\\(} and \exmp{\\)} are used to define the text
+ matched by the enclosed regular expression, and then subsequently
+ referred to \exmp{\\1}.
+
+ Finally, remember that when used in string literals either in the
+ \slang language or in the C language, care must be taken to
+ "double-up" the \exmp{'\\'} character since both languages treat it
+ as an escape character.
+
+\sect{Differences between \slang and egrep REs}
+
+ There are several differences between \slang regular expressions and,
+ e.g., \bf{egrep} regular expressions.
+
+ The most notable difference is that the \slang regular expressions do
+ not support the \bf{OR} operator \exmp{|} in expressions. This means
+ that \exmp{"a|b"} or \exmp{"a\\|b"} do not have the meaning that they
+ have in regular expression packages that support egrep-style
+ expressions.
+
+ The other main difference is that while \slang regular expressions
+ support the grouping operators \exmp{\\(} and \exmp{\\)}, they are
+ only used as a means of specifying the text that is matched. That
+ is, the expression
+#v+
+ "@\([a-z]*\)@.*@\1@"
+#v-
+ matches \exmp{"xxx@abc@silly@abc@yyy"}, where the pattern \exmp{\\1}
+ matches the text enclosed by the \exmp{\\(} and \exmp{\\)}
+ expressions. However, in the current implementation, the grouping
+ operators are not used to group regular expressions to form a single
+ regular expression. Thus expression such as \exmp{"\\(hello\\)*"} is
+ \em{not} a pattern to match zero or more occurances of \exmp{"hello"}
+ as it is in e.g., \bf{egrep}.
+
+ One question that comes up from time to time is why doesn't \slang
+ simply employ some posix-compatible regular expression library. The
+ simple answer is that, at the time of this writing, none exists that
+ is available across all the platforms that the \slang library
+ supports (Unix, VMS, OS/2, win32, win16, BEOS, MSDOS, and QNX) and
+ can be distributed under both the GNU and Artistic licenses. It is
+ particularly important that the library and the interpreter support a
+ common set of regular expressions in a platform independent manner.
+
diff --git a/libslang/doc/tm/rtl/array.tm b/libslang/doc/tm/rtl/array.tm
new file mode 100644
index 0000000..7f55ba3
--- /dev/null
+++ b/libslang/doc/tm/rtl/array.tm
@@ -0,0 +1,378 @@
+\function{_isnull}
+\synopsis{Check array for NULL elements}
+\usage{Char_Type[] = _isnull (a[])}
+\description
+ This function may be used to test for the presence of NULL elements
+ of an array. Specifically, it returns a \var{Char_Type} array of
+ with the same number of elements and dimensionality of the input
+ array. If an element of the input array is \NULL, then the
+ corresponding element of the output array will be set to \1,
+ otherwise it will be set to \0.
+\example
+ Set all \NULL elements of a string array \exmp{A} to the empty
+ string \exmp{""}:
+#v+
+ A[where(_isnull(A))] = "";
+#v-
+\notes
+ It is important to understand the difference between \exmp{A==NULL}
+ and \exmp{_isnull(A)}. The latter tests all elements of \exmp{A}
+ against \NULL, whereas the former only tests \exmp{A} itself.
+\seealso{where, array_map}
+\done
+
+\function{_reshape}
+\synopsis{Copy an array to a new shape}
+\usage{Array_Type _reshape (Array_Type A, Array_Type I)}
+\description
+ The \var{_reshape} function creates a copy of an array \var{A},
+ reshapes it to the form specified by \var{I} and returns the result.
+ The elements of \var{I} specify the new dimensions of the copy of
+ \var{A} and must be consistent with the number of elements \var{A}.
+\example
+ If \var{A} is a \var{100} element 1-d array, a new array 2-d array of
+ size \var{20} by \var{5} may be created from the elements of \var{A}
+ by
+#v+
+ A = _reshape (A, [20, 5]);
+#v-
+ In this example, the original array was no longer needed. Hence, it
+ is preferable to make use of the \var{__tmp} operator to avoid the
+ creation of a new array, i.e.,
+#v+
+ A = _reshape (__tmp(A), [20,5]);
+#v-
+\notes
+ The \var{reshape} function performs a similar function to
+ \var{_reshape}. In fact, the \var{_reshape} function could have been
+ implemented via:
+#v+
+ define _reshape (a, i)
+ {
+ a = @a; % Make a new copy
+ reshape (a, i);
+ return a;
+ }
+#v-
+\seealso{reshape, array_info}
+\done
+
+\function{array_info}
+\synopsis{Returns information about an array}
+\usage{(Array_Type, Integer_Type, DataType_Type) array_info (Array_Type a)}
+\description
+ The \var{array_info} function returns information about the array \var{a}.
+ It returns three values: an 1-d integer array specifying the
+ size of each dimension of \var{a}, the number of dimensions of
+ \var{a}, and the data type of \var{a}.
+\example
+ The \var{array_info} function may be used to find the number of rows
+ of an array:
+#v+
+ define num_rows (a)
+ {
+ variable dims, num_dims, data_type;
+
+ (dims, num_dims, data_type) = array_info (a);
+ return dims [0];
+ }
+#v-
+ For 1-d arrays, this information is more easily obtained from the
+ \var{length} function.
+\seealso{typeof, reshape, length, _reshape}
+\done
+
+\function{array_map}
+\synopsis{Apply a function to each element of an array}
+\usage{Array_Type array_map (type, func, arg0, ...)}
+#v+
+ DataType_Type type;
+ Ref_Type func;
+#v-
+\description
+ The \var{array_map} function may be used to apply a function to each
+ element of an array and returns the result as an array of a
+ specified type. The \var{type} parameter indicates what kind of
+ array should be returned and generally corresponds to the return
+ type of the function. The \var{arg0} parameter should be an array
+ and is used to determine the dimensions of the resulting array. If
+ any subsequent arguments correspond to an array of the same size,
+ then those array elements will be passed in parallel with the first
+ arrays arguments.
+\example
+ The first example illustrates how to apply the \var{strlen} function
+ to an array of strings:
+#v+
+ S = ["", "Train", "Subway", "Car"];
+ L = array_map (Integer_Type, &strlen, S);
+#v-
+ This is equivalent to:
+#v+
+ S = ["", "Train", "Subway", "Car"];
+ L = Integer_Type [length (S)];
+ for (i = 0; i < length (S); i++) L[i] = strlen (S[i]);
+#v-
+
+ Now consider an example involving the \var{strcat} function:
+#v+
+ files = ["slang", "slstring", "slarray"];
+
+ exts = ".c";
+ cfiles = array_map (String_Type, &strcat, files, exts);
+ % ==> cfiles = ["slang.c slstring.c slarray.c"];
+
+ exts = [".a",".b",".c"];
+ xfiles = array_map (String_Type, &strcat, files, exts);
+ % ==> xfiles = ["slang.a", "slstring.b", "slarray.c"];
+#v-
+\notes
+ Many mathemetical functions already work transparantly on arrays.
+ For example, the following two statements produce identical results:
+#v+
+ B = sin (A);
+ B = array_map (Double_Type, &sin, A);
+#v-
+\seealso{array_info, strlen, strcat, sin}
+\done
+
+\function{array_sort}
+\synopsis{Sort an array}
+\usage{Array_Type array_sort (Array_Type a [, String_Type or Ref_Type f])}
+\description
+ \var{array_sort} sorts the array \var{a} into ascending order and
+ returns an integer array that represents the result of the sort. If
+ the optional second parameter \var{f} is present, the function
+ specified by \var{f} will be used to compare elements of \var{a};
+ otherwise, a built-in sorting function will be used.
+
+ If \var{f} is present, then it must be either a string representing
+ the name of the comparison function, or a reference to the function.
+ The sort function represented by \var{f} must be a \slang
+ user-defined function that takes two arguments. The function must
+ return an integer that is less than zero if the first parameter is
+ considered to be less than the second, zero if they are equal, and a
+ value greater than zero if the first is greater than the second.
+
+ If the comparision function is not specified, then a built-in comparison
+ function appropriate for the data type will be used. For example,
+ if \var{a} is an array of character strings, then the sort will be
+ preformed using \var{strcmp}.
+
+ The integer array returned by this function is simply an index that
+ indicates the order of the sorted array. The input array \var{a} is
+ not changed.
+\example
+ An array of strings may be sorted using the \var{strcmp} function
+ since it fits the specification for the sorting function described
+ above:
+#v+
+ variable A = String_Type [3];
+ A[0] = "gamma"; A[1] = "alpha"; A[2] = "beta";
+
+ variable I = array_sort (A, &strcmp);
+#v-
+ Alternatively, one may use
+#v+
+ variable I = array_sort (A);
+#v-
+ to use the built-in comparison function.
+
+ After the \var{array_sort} has executed, the variable \var{I} will
+ have the values \exmp{[2, 0, 1]}. This array can be used to
+ re-shuffle the elements of \var{A} into the sorted order via the
+ array index expression \exmp{A = A[I]}.
+\seealso{strcmp}
+\done
+
+\function{cumsum}
+\synopsis{Compute the cumulative sum of an array}
+\usage{result = cumsum (Array_Type a [, Int_Type dim])}
+\description
+ The \var{cumsum} function performs a cumulative sum over the
+ elements of a numeric array and returns the resulting. If a second
+ argument is given, then it specifies the dimension of the array to
+ be summed over. For example, the cumulative sum of
+ \exmp{[1,2,3,4]}, is the array \exmp{[1,1+2,1+2+3,1+2+3+4]}, i.e.,
+ \exmp{[1,3,6,10]}.
+\seealso{sum}
+\done
+
+\function{init_char_array}
+\synopsis{Initialize an array of characters}
+\usage{init_char_array (Array_Type a, String_Type s)}
+\description
+ The \var{init_char_array} function may be used to initialize a
+ character array \var{a} by setting the elements of the array
+ \var{a} to the corresponding characters of the string \var{s}.
+\example
+ The statements
+#v+
+ variable a = Char_Type [10];
+ init_char_array (a, "HelloWorld");
+#v-
+ creates an character array and initializes its elements to the
+ characters in the string \exmp{"HelloWorld"}.
+\notes
+ The character array must be large enough to hold all the characters
+ of the initialization string.
+\seealso{bstring_to_array, strlen, strcat}
+\done
+
+\function{length}
+\synopsis{Get the length of an object}
+\usage{Integer_Type length (obj)}
+\description
+ The \var{length} function may be used to get information about the
+ length of an object. For simple scalar data-types, it returns \1.
+ For arrays, it returns the total number of elements of the array.
+\notes
+ If \var{obj} is a string, \var{length} returns \1 because a
+ \var{String_Type} object is considered to be a scalar. To get the
+ number of characters in a string, use the \var{strlen} function.
+\seealso{array_info, typeof, strlen}
+\done
+
+\function{max}
+\synopsis{Get the maximum value of an array}
+\usage{result = max (Array_Type a [,Int_Type dim])}
+\description
+ The \var{max} function examines the elements of a numeric array and
+ returns the value of the largest element. If a second argument is
+ given, then it specifies the dimension of the array to be searched.
+ In this case, an array of dimension one less than that of the input array
+ will be returned with the corresponding elements in the specified
+ dimension replaced by the minimum value in that dimension.
+\example
+ Consider the 2-d array
+#v+
+ 1 2 3 4 5
+ 6 7 8 9 10
+#v-
+ generated by
+#v+
+ a = _reshape ([1:10], [2, 5]);
+#v-
+ Then \exmp{max(a)} will return \exmp{10}, and \exmp{max(a,0)} will return
+ a 1-d array with elements
+#v+
+ 6 7 8 9 10
+#v-
+\seealso{max, sum, reshape}
+\done
+
+\function{min}
+\synopsis{Get the minimum value of an array}
+\usage{result = min (Array_Type a [,Int_Type dim])}
+\description
+ The \var{min} function examines the elements of a numeric array and
+ returns the value of the smallest element. If a second argument is
+ given, then it specifies the dimension of the array to be searched.
+ In this case, an array of dimension one less than that of the input array
+ will be returned with the corresponding elements in the specified
+ dimension replaced by the minimum value in that dimension.
+\example
+ Consider the 2-d array
+#v+
+ 1 2 3 4 5
+ 6 7 8 9 10
+#v-
+ generated by
+#v+
+ a = _reshape ([1:10], [2, 5]);
+#v-
+ Then \exmp{min(a)} will return \exmp{1}, and \exmp{min(a,0)} will return
+ a 1-d array with elements
+#v+
+ 1 2 3 4 5
+#v-
+\seealso{max, sum, reshape}
+\done
+
+\function{reshape}
+\synopsis{Reshape an array}
+\usage{reshape (Array_Type A, Array_Type I)}
+\description
+ The \var{reshape} function changes the size of \var{A} to have the size
+ specified by the 1-d integer array \var{I}. The elements of \var{I}
+ specify the new dimensions of \var{A} and must be consistent with
+ the number of elements \var{A}.
+\example
+ If \var{A} is a \var{100} element 1-d array, it can be changed to a
+ 2-d \var{20} by \var{5} array via
+#v+
+ reshape (A, [20, 5]);
+#v-
+ However, \exmp{reshape(A, [11,5])} will result in an error because
+ the \exmp{[11,5]} array specifies \exmp{55} elements.
+\notes
+ Since \var{reshape} modifies the shape of an array, and arrays are
+ treated as references, then all references to the array will
+ reference the new shape. If this effect is unwanted, then use the
+ \var{_reshape} function instead.
+\seealso{_reshape, array_info}
+\done
+
+\function{sum}
+\synopsis{Sum over the elements of an array}
+\usage{result = sum (Array_Type a [, Int_Type dim])}
+\description
+ The \var{sum} function sums over the elements of a numeric array and
+ returns its result. If a second argument is given, then it
+ specifies the dimension of the array to be summed over. In this
+ case, an array of dimension one less than that of the input array
+ will be returned.
+
+ If the input array is an integer type, then the resulting value will
+ be a \var{Double_Type}. If the input array is a \var{Float_Type},
+ then the result will be a \var{Float_Type}.
+\example
+ The mean of an array \exmp{a} of numbers is
+#v+
+ sum(a)/length(a)
+#v-
+\seealso{cumsum, transpose, reshape}
+\done
+
+\function{transpose}
+\synopsis{Transpose an array}
+\usage{Array_Type transpose (Array_Type a)}
+\description
+ The \var{transpose} function returns the transpose of a specified
+ array. By definition, the transpose of an array, say one with
+ elements \exmp{a[i,j,...k]} is an array whose elements are
+ \exmp{a[k,...,j,i]}.
+\seealso{_reshape, reshape, sum, array_info}
+\done
+
+\function{where}
+\synopsis{Get indices where an integer array is non-zero}
+\usage{Array_Type where (Array_Type a)}
+\description
+ The \var{where} function examines an numeric array \var{a} and
+ returns an integer array giving the indices of \var{a}
+ where the corresponding element of \var{a} is non-zero.
+
+ Although this function may appear to be simple or even trivial, it
+ is arguably one of the most important and powerful functions for
+ manipulating arrays.
+\example
+ Consider the following:
+#v+
+ variable X = [0.0:10.0:0.01];
+ variable A = sin (X);
+ variable I = where (A < 0.0);
+ A[I] = cos (X) [I];
+#v-
+ Here the variable \var{X} has been assigned an array of doubles
+ whose elements range from \exmp{0.0} through \exmp{10.0} in
+ increments of \var{0.01}. The second statement assigns \var{A} to
+ an array whose elements are the \var{sin} of the elements of \var{X}.
+ The third statement uses the where function to get the indices of
+ the elements of \var{A} that are less than \var{0.0}. Finally, the
+ last statement substitutes into \var{A} the \var{cos} of the
+ elements of \var{X} at the positions of \var{A} where the
+ corresponding \var{sin} is less than \var{0}. The end result is
+ that the elements of \var{A} are a mixture of sines and cosines.
+\seealso{array_info, sin, cos}
+\done
+
diff --git a/libslang/doc/tm/rtl/assoc.tm b/libslang/doc/tm/rtl/assoc.tm
new file mode 100644
index 0000000..e5f0dc6
--- /dev/null
+++ b/libslang/doc/tm/rtl/assoc.tm
@@ -0,0 +1,76 @@
+\function{assoc_delete_key}
+\synopsis{Delete a key from an Associative Array}
+\usage{assoc_delete_key (Assoc_Type a, String_Type k)}
+\description
+ The \var{assoc_delete_key} function deletes a key given by \var{k}
+ from the associative array \var{a}. If the specified key does not
+ exist in \var{a}, then this function has no effect.
+\seealso{assoc_key_exists, assoc_get_keys}
+\done
+
+\function{assoc_get_keys}
+\synopsis{Return all the key names of an Associative Array}
+\usage{String_Type[] assoc_get_keys (Assoc_Type a)}
+\description
+ This function returns all the key names of an associative array
+ \var{a} as an ordinary one dimensional array of strings. If the
+ associative array contains no keys, an empty array will be returned.
+\example
+ The following function computes the number of keys in an associative
+ array:
+#v+
+ define get_num_elements (a)
+ {
+ return length (assoc_get_keys (a));
+ }
+#v-
+\seealso{assoc_get_values, assoc_key_exists, assoc_delete_key, length}
+\done
+
+\function{assoc_get_values}
+\synopsis{Return all the values of an Associative Array}
+\usage{Array_Type assoc_get_keys (Assoc_Type a)}
+\description
+ This function returns all the values in the associative array
+ \var{a} as an array of proper type. If the associative array
+ contains no keys, an empty array will be returned.
+\example
+ Suppose that \var{a} is an associative array of type
+ \var{Integer_Type}, i.e., it was created via
+#v+
+ variable a = Assoc_Type[Integer_Type];
+#v-
+ The the following may be used to print the values of the array in
+ ascending order:
+#v+
+ static define int_sort_fun (x, y)
+ {
+ return sign (x - y);
+ }
+ define sort_and_print_values (a)
+ {
+ variable i, v;
+
+ v = assoc_get_values (a);
+ i = array_sort (v, &int_sort_fun);
+ v = v[i];
+ foreach (v)
+ {
+ variable vi = ();
+ () = fprintf (stdout, "%d\n", vi);
+ }
+ }
+#v-
+\seealso{assoc_get_values, assoc_key_exists, assoc_delete_key, array_sort}
+\done
+
+\function{assoc_key_exists}
+\synopsis{Check to see whether a key exists in an Associative Array}
+\usage{Integer_Type assoc_key_exists (Assoc_Type a, String_Type k)}
+\description
+ The \var{assoc_key_exists} function may be used to determine whether
+ or not a specified key \var{k} exists in an associative array \var{a}.
+ It returns \1 if the key exists, or \0 if it does not.
+\seealso{assoc_get_keys, assoc_get_values, assoc_delete_key}
+\done
+
diff --git a/libslang/doc/tm/rtl/bstr.tm b/libslang/doc/tm/rtl/bstr.tm
new file mode 100644
index 0000000..ffe2825
--- /dev/null
+++ b/libslang/doc/tm/rtl/bstr.tm
@@ -0,0 +1,151 @@
+\function{array_to_bstring}
+\synopsis{Convert an array to a binary string}
+\usage{BString_Type array_to_bstring (Array_Type a)}
+\description
+ The \var{array_to_bstring} function returns the elements of an
+ array \var{a} as a binary string.
+\seealso{bstring_to_array, init_char_array}
+\done
+
+\function{bstring_to_array}
+\synopsis{Convert a binary string to an array of characters}
+\usage{UChar_Type[] bstring_to_array (BString_Type b)}
+\description
+ The \var{bstring_to_array} function returns an array of unsigned
+ characters whose elements correspond to the characters in the
+ binary string.
+\seealso{array_to_bstring, init_char_array}
+\done
+
+\function{bstrlen}
+\synopsis{Get the length of a binary string}
+\usage{UInt_Type bstrlen (BString_Type s)}
+\description
+ The \var{bstrlen} function may be used to obtain the length of a
+ binary string. A binary string differs from an ordinary string (a C
+ string) in that a binary string may include null chracters.
+\example
+#v+
+ variable s = "hello\0";
+ len = bstrlen (s); % ==> len = 6
+ len = strlen (s); % ==> len = 5
+#v-
+\seealso{strlen, length}
+\done
+
+\function{pack}
+\synopsis{Pack objects into a binary string}
+\usage{BString_Type pack (String_Type fmt, ...)}
+\description
+ The \var{pack} function combines zero or more the objects (represented
+ by the ellipses above) into a binary string acording to the format
+ string \var{fmt}.
+
+ The format string consists of one or more data-type specification
+ characters, and each may be followed by an optional decimal length
+ specifier. Specifically, the data-types are specified according to
+ the following table:
+#v+
+ c char
+ C unsigned char
+ h short
+ H unsigned short
+ i int
+ I unsigned int
+ l long
+ L unsigned long
+ j 16 bit int
+ J 16 unsigned int
+ k 32 bit int
+ K 32 bit unsigned int
+ f float
+ d double
+ F 32 bit float
+ D 64 bit float
+ s character string, null padded
+ S character string, space padded
+ x a null pad character
+#v-
+ A decimal length specifier may follow the data-type specifier. With
+ the exception of the \var{s} and \var{S} specifiers, the length
+ specifier indicates how many objects of that data type are to be
+ packed or unpacked from the string. When used with the \var{s} or
+ \var{S} specifiers, it indicates the field width to be used. If the
+ length specifier is not present, the length defaults to one.
+
+ With the exception of \var{c}, \var{C}, \var{s}, \var{S}, and
+ \var{x}, each of these may be prefixed by a character that indicates
+ the byte-order of the object:
+#v+
+ > big-endian order (network order)
+ < little-endian order
+ = native byte-order
+#v-
+ The default is to use native byte order.
+
+ When unpacking via the \var{unpack} function, if the length
+ specifier is greater than one, then an array of that length will be
+ returned. In addition, trailing whitespace and null character are
+ stripped when unpacking an object given by the \var{S} specifier.
+\example
+#v+
+ a = pack ("cc", 'A', 'B'); % ==> a = "AB";
+ a = pack ("c2", 'A', 'B'); % ==> a = "AB";
+ a = pack ("xxcxxc", 'A', 'B'); % ==> a = "\0\0A\0\0B";
+ a = pack ("h2", 'A', 'B'); % ==> a = "\0A\0B" or "\0B\0A"
+ a = pack (">h2", 'A', 'B'); % ==> a = "\0\xA\0\xB"
+ a = pack ("<h2", 'A', 'B'); % ==> a = "\0B\0A"
+ a = pack ("s4", "AB", "CD"); % ==> a = "AB\0\0"
+ a = pack ("s4s2", "AB", "CD"); % ==> a = "AB\0\0CD"
+ a = pack ("S4", "AB", "CD"); % ==> a = "AB "
+ a = pack ("S4S2", "AB", "CD"); % ==> a = "AB CD"
+#v-
+\seealso{unpack, sizeof_pack, pad_pack_format, sprintf}
+\done
+
+\function{pad_pack_format}
+\synopsis{Add padding to a pack format}
+\usage{BString_Type pad_pack_format (String_Type fmt)}
+\description
+ The \var{pad_pack_format} function may be used to add the
+ appropriate padding to the format \var{fmt} such that the data types
+ specified by the format will be properly aligned for the system.
+ This is especially important when reading or writing files that
+ assume the native alignment.
+
+ See the S-Lang User's Guide for more information about the use of
+ this function.
+\seealso{pack, unpack, sizeof_pack}
+\done
+
+\function{sizeof_pack}
+\synopsis{Compute the size implied by a pack format string}
+\usage{UInt_Type sizeof_pack (String_Type fmt)}
+\description
+ The \var{sizeof_pack} function returns the size of the binary string
+ represented by the format string \var{fmt}. This information may be
+ needed when reading a structure from a file.
+\notes
+\seealso{pack, unpack, pad_pack_format}
+\done
+
+\function{unpack}
+\synopsis{Unpack Objects from a Binary String}
+\usage{(...) = unpack (String_Type fmt, BString_Type s)}
+\description
+ The \var{unpack} function unpacks objects from a binary string
+ \var{s} according to the format \var{fmt} and returns the objects to
+ the stack in the order in which they were unpacked. See the
+ documentation of the \var{pack} function for details about the
+ format string.
+\example
+#v+
+ (x,y) = unpack ("cc", "AB"); % ==> x = 'A', y = 'B'
+ x = unpack ("c2", "AB"); % ==> x = ['A', 'B']
+ x = unpack ("x<H", "\0\xAB\xCD"); % ==> x = 0xCDABuh
+ x = unpack ("xxs4", "a b c\0d e f"); % ==> x = "b c\0"
+ x = unpack ("xxS4", "a b c\0d e f"); % ==> x = "b c"
+#v-
+\seealso{pack, sizeof_pack, pad_pack_format}
+\done
+
diff --git a/libslang/doc/tm/rtl/debug.tm b/libslang/doc/tm/rtl/debug.tm
new file mode 100644
index 0000000..682c4b8
--- /dev/null
+++ b/libslang/doc/tm/rtl/debug.tm
@@ -0,0 +1,98 @@
+\function{_clear_error}
+\synopsis{Clear an error condition}
+\usage{_clear_error ()}
+\description
+ This function may be used in error-blocks to clear the error that
+ triggered execution of the error block. Execution resumes following
+ the statement, in the scope of the error-block, that triggered the
+ error.
+\example
+ Consider the following wrapper around the \var{putenv} function:
+#v+
+ define try_putenv (name, value)
+ {
+ variable status;
+ ERROR_BLOCK
+ {
+ _clear_error ();
+ status = -1;
+ }
+ status = 0;
+ putenv (sprintf ("%s=%s", name, value);
+ return status;
+ }
+#v-
+ If \var{putenv} fails, it generates an error condition, which the
+ \var{try_putenv} function catches and clears. Thus \var{try_putenv}
+ is a function that returns \exmp{-1} upon failure and \var{0} upon
+ success.
+\seealso{_trace_function, _slangtrace, _traceback}
+\done
+
+\variable{_debug_info}
+\synopsis{Configure debugging information}
+\usage{Integer_Type _debug_info}
+\description
+ The \var{_debug_info} variable controls whether or not extra code
+ should be generated for additional debugging and traceback
+ information. Currently, if \var{_debug_info} is zero, no extra code
+ will be generated; otherwise extra code will be inserted into the
+ compiled bytecode for additional debugging data.
+
+ The value of this variable is local to each compilation unit and
+ setting its value in one unit has no effect upon its value in other
+ units.
+\example
+#v+
+ _debug_info = 1; % Enable debugging information
+#v-
+\notes
+ Setting this variable to a non-zero value may slow down the
+ interpreter somewhat.
+\seealso{_traceback, _slangtrace}
+\done
+
+\variable{_slangtrace}
+\synopsis{Turn function tracing on or off.}
+\usage{Integer_Type _slangtrace}
+\description
+ The \var{_slangtrace} variable is a debugging aid that when set to a
+ non-zero value enables tracing when function declared by
+ \var{_trace_function} is entered. If the value is greater than
+ zero, both intrinsic and user defined functions will get traced.
+ However, if set to a value less than zero, intrinsic functions will
+ not get traced.
+\seealso{_trace_function, _traceback, _print_stack}
+\done
+
+\function{_trace_function}
+\synopsis{Set the function to trace}
+\usage{_trace_function (String_Type f)}
+\description
+ \var{_trace_function} declares that the \slang function with name
+ \var{f} is to be traced when it is called. Calling
+ \var{_trace_function} does not in itself turn tracing on. Tracing
+ is turned on only when the variable \var{_slangtrace} is non-zero.
+\seealso{_slangtrace, _traceback}
+\done
+
+\variable{_traceback}
+\synopsis{Generate a traceback upon error}
+\usage{Integer_Type _traceback}
+\description
+ \var{_traceback} is an intrinsic integer variable whose value
+ controls whether or not a traceback of the call stack is to be
+ generated upon error. If \var{_traceback} is greater than zero, a
+ full traceback will be generated, which includes the values of local
+ variables. If the value is less than zero, a traceback will be
+ generated without local variable information, and if
+ \var{_traceback} is zero the traceback will not be generated.
+
+ Local variables are represented in the form \var{$n} where \var{n} is an
+ integer numbered from zero. More explicitly, \var{$0} represents the
+ first local variable, \var{$1} represents the second, and so on.
+ Please note that function parameters are local variables and that the
+ first parameter corresponds to \var{$0}.
+\seealso{_slangtrace, error}
+\done
+
diff --git a/libslang/doc/tm/rtl/dir.tm b/libslang/doc/tm/rtl/dir.tm
new file mode 100644
index 0000000..a25fc86
--- /dev/null
+++ b/libslang/doc/tm/rtl/dir.tm
@@ -0,0 +1,223 @@
+\function{chdir}
+\synopsis{Change the current working directory.}
+\usage{Integer_Type chdir (String_Type dir)}
+\description
+ The \var{chdir} function may be used to changed the current working
+ directory to the directory specified by \var{dir}. Upon success it
+ returns zero; however, upon failure it returns \exmp{-1} and sets
+ \var{errno} accordingly.
+\seealso{mkdir, stat_file}
+\done
+
+\function{chmod}
+\synopsis{Change the mode of a file}
+\usage{Integer_Type chmod (String_Type file, Integer_Type mode)}
+\description
+ The \var{chmod} function changes the permissions of \var{file} to those
+ specified by \var{mode}. It returns \exmp{0} upon success, or
+ \exmp{-1} upon failure setting \var{errno} accordingly.
+
+ See the system specific documentation for the C library
+ function \var{chmod} for a discussion of the \var{mode} parameter.
+\seealso{chown, stat_file}
+\done
+
+\function{chown}
+\synopsis{Change the owner of a file}
+\usage{Integer_Type chown (String_Type file, Integer_Type uid, Integer_Type gid)}
+\description
+ The \var{chown} function is used to change the user-id and group-id of
+ \var{file} to \var{uid} and \var{gid}, respectively. It returns
+ \var{zero} upon success and \exmp{-1} upon failure, with \var{errno}
+ set accordingly.
+\notes
+ On most systems, only the super user can change the ownership of a
+ file.
+
+ Some systems do not support this function.
+\seealso{chmod, stat_file}
+\done
+
+\function{getcwd}
+\synopsis{Get the current working directory}
+\usage{String_Type getcwd ()}
+\description
+ The \var{getcwd} function returns the absolute pathname of the
+ current working directory. If an error occurs or it cannot
+ determine the working directory, it returns \var{NULL} and sets
+ \var{errno} accordingly.
+\notes
+ Under Unix, OS/2, and MSDOS, the pathname returned by this function
+ includes the trailing slash character. Some versions also include
+ the drive specifier.
+\seealso{mkdir, chdir, errno}
+\done
+
+\function{listdir}
+\synopsis{Get a list of the files in a directory}
+\usage{String_Type[] listdir (String_Type dir)}
+\description
+ The \var{listdir} function returns the directory listing of all the
+ files in the specified directory \var{dir} as an array of strings.
+ It does not return the special files \exmp{".."} and \exmp{"."} as
+ part of the list.
+\seealso{stat_file, stat_is, length}
+\done
+
+\function{lstat_file}
+\synopsis{Get information about a symbolic link}
+\usage{Struct_Type lstat_file (String_Type file)}
+\description
+ The \var{lstat_file} function behaves identically to \var{stat_file}
+ but if \var{file} is a symbolic link, \var{lstat_file} returns
+ information about the link itself, and not the file that it
+ references.
+
+ See the documentation for \var{stat_file} for more information.
+\notes
+ On systems that do not support symbolic links, there is no
+ difference between this function and the \var{stat_file} function.
+\seealso{stat_file, readlink}
+\done
+
+\function{mkdir}
+\synopsis{Create a new directory}
+\usage{Integer_Type mkdir (String_Type dir, Integer_Type mode)}
+\description
+ The \var{mkdir} function creates a directory whose name is specified
+ by the \var{dir} parameter with permissions specified by \var{mode}.
+ Upon success \var{mkdir} returns zero, or it returns \exmp{-1} and
+ sets \var{errno} accordingly. In particular, if the directory
+ already exists, the function will fail and set errno to
+ \var{EEXIST}.
+\example
+#v+
+ define my_mkdir (dir)
+ {
+ if (0 == mkdir (dir, 0777)) return;
+ if (errno == EEXIST) return;
+ verror ("mkdir %s failed: %s", dir, errno_string (errno));
+ }
+#v-
+\notes
+ The \var{mode} parameter may not be meaningful on all systems. On
+ systems where it is meaningful, the actual permissions on the newly
+ created directory are modified by the process's umask.
+\seealso{rmdir, getcwd, chdir, fopen, errno}
+\done
+
+\function{readlink}
+\synopsis{String_Type readlink (String_Type path)}
+\usage{Get the value of a symbolic link}
+\description
+ The \var{readlink} function returns the value of a symbolic link and
+ returns it as a string. Upon failure, \NULL is returned and
+ \var{errno} set accordingly.
+\notes
+ Not all systems support this function.
+\seealso{lstat_file, stat_file, stat_is}
+\done
+
+\function{remove}
+\synopsis{Delete a file}
+\usage{Integer_Type remove (String_Type file)}
+\description
+ The \var{remove} function deletes a file. It returns \0 upon
+ success, or \-1 upon error and sets \var{errno} accordingly.
+\seealso{rename, rmdir}
+\done
+
+\function{rename}
+\synopsis{Rename a file}
+\usage{Integer_Type rename (String_Type old, String_Type new)}
+\description
+ The \var{rename} function renames a file from \var{old} to \var{new}
+ moving it between directories if necessary. This function may fail
+ if the directories do not refer to the same file system. It returns
+ \0 upon success, or \-1 upon error and sets \var{errno} accordingly.
+\seealso{remove, errno}
+\done
+
+\function{rmdir}
+\synopsis{Remove a directory}
+\usage{Integer_Type rmdir (String_Type dir)}
+\description
+ The \var{rmdir} function deletes a specified directory. It returns
+ \0 upon success or \-1 upon error and sets \var{errno} accordingly.
+\notes
+ The directory must be empty before it can be removed.
+\seealso{rename, remove, mkdir}
+\done
+
+\function{stat_file}
+\synopsis{Get information about a file}
+\usage{Struct_Type stat_file (String_Type file)}
+\description
+ The \var{stat_file} function returns information about \var{file}
+ through the use of the system \var{stat} call. If the stat call
+ fails, the function returns \var{NULL} and sets errno accordingly.
+ If it is successful, it returns a stat structure with the following
+ integer fields:
+#v+
+ st_dev
+ st_ino
+ st_mode
+ st_nlink
+ st_uid
+ st_gid
+ st_rdev
+ st_size
+ st_atime
+ st_mtime
+ st_ctime
+#v-
+ See the man page for \var{stat} for a discussion of these fields.
+\example
+ The following example shows how the \var{stat_file} function may be
+ used to get the size of a file:
+#v+
+ define file_size (file)
+ {
+ variable st;
+ st = stat_file(file);
+ if (st == NULL) verror ("Unable to stat %s", file);
+ return st.st_size;
+ }
+#v-
+\seealso{lstat_file, stat_is}
+\done
+
+\function{stat_is}
+\synopsis{Parse the \var{st_mode} field of a stat structure}
+\usage{Char_Type stat_is (String_Type type, Integer_Type st_mode)}
+\description
+ The \var{stat_is} function returns a signed character value about
+ the type of file specified by \var{st_mode}. Specifically,
+ \var{type} must be one of the strings:
+#v+
+ "sock" (socket)
+ "fifo" (fifo)
+ "blk" (block device)
+ "chr" (character device)
+ "reg" (regular file)
+ "lnk" (link)
+ "dir" (dir)
+#v-
+ It returns a non-zero value if \var{st_mode} corresponds to
+ \var{type}.
+\example
+ The following example illustrates how to use the \var{stat_is}
+ function to determine whether or not a file is a directory:
+#v+
+ define is_directory (file)
+ {
+ variable st;
+
+ st = stat_file (file);
+ if (st == NULL) return 0;
+ return stat_is ("dir", st.st_mode);
+ }
+#v-
+\seealso{stat_file, lstat_file}
+\done
+
diff --git a/libslang/doc/tm/rtl/eval.tm b/libslang/doc/tm/rtl/eval.tm
new file mode 100644
index 0000000..3c1e66c
--- /dev/null
+++ b/libslang/doc/tm/rtl/eval.tm
@@ -0,0 +1,119 @@
+\function{autoload}
+\synopsis{Load a function from a file}
+\usage{autoload (String_Type funct, String_Type file)}
+\description
+ The \var{autoload} function is used to declare \var{funct} to the
+ interpreter and indicate that it should be loaded from \var{file} when
+ it is actually used.
+\example
+ Suppose \var{bessel_j0} is a function defined in the file
+ \var{bessel.sl}. Then the statement
+#v+
+ autoload ("bessel_j0", "bessel.sl");
+#v-
+ will cause \var{bessel.sl} to be loaded prior to the execution of
+ \var{bessel_j0}
+\seealso{evalfile}
+\done
+
+\function{byte_compile_file}
+\synopsis{Compile a file to byte-code for faster loading.}
+\usage{byte_compile_file (String_Type file, Integer_Type method)}
+\description
+ The \var{byte_compile_file} function byte-compiles \var{file}
+ producing a new file with the same name except a \var{'c'} is added
+ to the output file name. For example, \var{file} is
+ \exmp{"site.sl"}, then the function produces a new file named
+ \exmp{site.slc}.
+\notes
+ The \var{method} parameter is not used in the current
+ implementation. Its use is reserved for the future. For now, set
+ it to \exmp{0}.
+\seealso{evalfile}
+\done
+
+\function{eval}
+\synopsis{Interpret a string as \slang code}
+\usage{eval (String_Type expression, [,String_Type namespace])}
+\description
+ The \var{eval} function parses a string as S-Lang code and executes the
+ result. If called with the optional namespace argument, then the
+ string will be evaluated in the specified namespace.
+
+ This is a useful function in many contexts such as dynamically
+ generating function definitions where there is no way to generate
+ them otherwise.
+\example
+#v+
+ if (0 == is_defined ("my_function"))
+ eval ("define my_function () { message (\"my_function\"); }");
+#v-
+\seealso{is_defined, autoload, evalfile}
+\done
+
+\function{evalfile}
+\synopsis{Interpret a file containing \slang code.}
+\usage{Integer_Type evalfile (String_Type file, [,String_Type namespace])}
+\description
+ The \var{evalfile} function loads \var{file} into the interpreter
+ and executes it. If called with the optional namespace argument,
+ the file will be loaded into the specified namespace, which will be
+ created if necessary. If no errors were encountered, \exmp{1} will
+ be returned; otherwise, a \slang error will be generated and the
+ function will return zero.
+\example
+#v+
+ define load_file (file)
+ {
+ ERROR_BLOCK { _clear_error (); }
+ () = evalfile (file);
+ }
+#v-
+\notes
+ For historical reasons, the return value of this function is not
+ really useful.
+
+ The file is searched along an application-defined load-path. The
+ \ifun{get_slang_load_path} and \ifun{set_slang_load_path} functions
+ may be used to set and query the path.
+\seealso{eval, autoload, set_slang_load_path, get_slang_load_path}
+\done
+
+\function{get_slang_load_path}
+\synopsis{Get the value of the interpreter's load-path}
+\usage{String_Type get_slang_load_path ()}
+\description
+ This function retrieves the value of the delimiter-separated search
+ path used for loading files.
+\notes
+ Some applications may not support the built-in load-path searching
+ facility provided by the underlying library.
+\seealso{}
+\done
+
+\function{set_slang_load_path}
+\synopsis{Set the value of the interpreter's load-path}
+\usage{set_slang_load_path (String_Type path)}
+\description
+ This function may be used to set the value of the
+ delimiter-separated search path used by the \ifun{evalfile} and
+ \ifun{autoload} functions for locating files.
+\example
+#v+
+ public define prepend_to_slang_load_path (p)
+ {
+ variable s = stat_file (p);
+ if (s == NULL) return;
+ if (0 == stat_is ("dir", s.st_mode))
+ return;
+
+ variable d = path_get_delimiter ();
+ set_slang_load_path (strcat (p, d, get_slang_load_path ()));
+ }
+#v-
+\notes
+ Some applications may not support the built-in load-path searching
+ facility provided by the underlying library.
+\seealso{get_slang_load_path, path_get_delimiter, evalfile, autoload}
+\done
+
diff --git a/libslang/doc/tm/rtl/import.tm b/libslang/doc/tm/rtl/import.tm
new file mode 100644
index 0000000..54dd5b6
--- /dev/null
+++ b/libslang/doc/tm/rtl/import.tm
@@ -0,0 +1,51 @@
+\function{get_import_module_path}
+\synopsis{Get the search path for dynamically loadable objects}
+\usage{String_Type get_import_module_path ()}
+\description
+ The \var{get_import_module_path} may be used to get the search path
+ for dynamically shared objects. Such objects may be made accessable
+ to the application via the \var{import} function.
+\seealso{import, set_import_module_path}
+\done
+
+\function{import}
+\synopsis{Dynamically link to a specified module}
+\usage{import (String_Type module [, String_Type namespace])}
+\description
+ The \var{import} function causes the run-time linker to dynamically
+ link to the shared object specified by the \var{module} parameter.
+ It seaches for the shared object as follows: First a search is
+ performed along all module paths specified by the application. Then
+ a search is made along the paths defined via the
+ \var{set_import_module_path} function. If not found, a search is
+ performed along the paths given by the \var{SLANG_MODULE_PATH}
+ environment variable. Finally, a system dependent search is
+ performed (e.g., using the \var{LD_LIBRARY_PATH} environment
+ variable).
+
+ The optional second parameter may be used to specify a namespace
+ for the intrinsic functions and variables of the module. If this
+ parameter is not present, the intrinsic objects will be placed into
+ the global namespace.
+
+ This function signals an error if the specified module is not found.
+\notes
+ The \var{import} function is not available on all systems.
+\seealso{set_import_module_path, use_namespace, current_namespace, getenv, evalfile}
+\done
+
+\function{set_import_module_path}
+\synopsis{Set the search path for dynamically loadable objects}
+\usage{set_import_module_path (String_Type path_list)}
+\description
+ The \var{set_import_module_path} may be used to set the search path
+ for dynamically shared objects. Such objects may be made accessable
+ to the application via the \var{import} function.
+
+ The actual syntax for the specification of the set of paths will
+ vary according to the operating system. Under Unix, a colon
+ character is used to separate paths in \var{path_list}. For win32
+ systems a semi-colon is used.
+\seealso{import, get_import_module_path}
+\done
+
diff --git a/libslang/doc/tm/rtl/info.tm b/libslang/doc/tm/rtl/info.tm
new file mode 100644
index 0000000..b476689
--- /dev/null
+++ b/libslang/doc/tm/rtl/info.tm
@@ -0,0 +1,202 @@
+\variable{_NARGS}
+\synopsis{The number of parameters passed to a function}
+\usage{Integer_Type _NARGS}
+ The value of the \var{_NARGS} variable represents the number of
+ arguments passed to the function. This variable is local to each
+ function.
+\example
+ This example uses the \var{_NARGS} variable to print the list of
+ values passed to the function:
+#v+
+ define print_values ()
+ {
+ variable arg;
+
+ if (_NARGS == 0)
+ {
+ message ("Nothing to print");
+ return;
+ }
+ foreach (__pop_args (_NARGS))
+ {
+ arg = ();
+ vmessage ("Argument value is: %S", arg.value);
+ }
+ }
+#v-
+\seealso{__pop_args, __push_args, typeof}
+\done
+
+\function{__get_defined_symbols}
+\synopsis{Get the symbols defined by the preprocessor}
+\usage{Integer_Type __get_defined_symbols ()}
+\description
+ The \var{__get_defined_symbols} functions is used to get the list of
+ all the symbols defined by the \slang preprocessor. It pushes each
+ of the symbols on the stack followed by the number of items pushed.
+\seealso{is_defined, _apropos, _get_namespaces}
+\done
+
+\function{__is_initialized}
+\synopsis{Determine whether or not a variable has a value}
+\usage{Integer_Type __is_initialized (Ref_Type r)}
+\description
+ This function returns non-zero of the object referenced by \var{r}
+ is initialized, i.e., whether it has a value. It returns \0 if the
+ referenced object has not been initialized.
+\example
+ For example, the function:
+#v+
+ define zero ()
+ {
+ variable f;
+ return __is_initialized (&f);
+ }
+#v-
+ will always return zero, but
+#v+
+ define one ()
+ {
+ variable f = 0;
+ return __is_initialized (&f);
+ }
+#v-
+ will return one.
+\notes
+ It is easy to see why a reference to the variable must be passed to
+ \var{__is_initialized} and not the variable itself; otherwise, the
+ value of the variable would be passed and the variable may have no
+ value if it was not initialized.
+\seealso{__get_reference, __uninitialize, is_defined, typeof, eval}
+\done
+
+\function{_apropos}
+\synopsis{Generate a list of functions and variables}
+\usage{Array_Type _apropos (String_Type ns, String_Type s, Integer_Type flags)}
+\description
+ The \var{_apropos} function may be used to get a list of all defined
+ objects in the namespace \var{ns} whose name matches the regular
+ expression \var{s} and whose type matches those specified by
+ \var{flags}. It returns an array of strings representing the
+ matches.
+
+ The second parameter \var{flags} is a bit mapped value whose bits
+ are defined according to the following table
+#v+
+ 1 Intrinsic Function
+ 2 User-defined Function
+ 4 Intrinsic Variable
+ 8 User-defined Variable
+#v-
+\example
+#v+
+ define apropos (s)
+ {
+ variable n, name, a;
+ a = _apropos ("Global", s, 0xF);
+
+ vmessage ("Found %d matches:", length (a));
+ foreach (a)
+ {
+ name = ();
+ message (name);
+ }
+ }
+#v-
+ prints a list of all matches.
+\notes
+ If the namespace specifier \var{ns} is the empty string \exmp{""},
+ then the namespace will default to the static namespace of the
+ current compilation unit.
+\seealso{is_defined, sprintf, _get_namespaces}
+\done
+
+\function{_function_name}
+\synopsis{Returns the name of the currently executing function}
+\usage{String_Type _function_name ()}
+\description
+ This function returns the name of the currently executing function.
+ If called from top-level, it returns the empty string.
+\seealso{_trace_function, is_defined}
+\done
+
+\function{_get_namespaces}
+\synopsis{Returns a list of namespace names}
+\usage{String_Type[] _get_namespaces ()}
+\description
+ This function returns a string array containing the names of the
+ currently defined namespaces.
+\seealso{_apropos, use_namespace, implements, __get_defined_symbols}
+\done
+
+\variable{_slang_doc_dir}
+\synopsis{Installed documentation directory}
+\usage{String_Type _slang_doc_dir;}
+\description
+ The \var{_slang_doc_dir} variable is a read-only whose value
+ specifies the installation location of the \slang documentation.
+\seealso{get_doc_string_from_file}
+\done
+
+\variable{_slang_version}
+\synopsis{The S-Lang library version number}
+\usage{Integer_Type _slang_version}
+\description
+ The \var{_slang_version} variable is read-only and whose
+ value represents the number of the \slang library.
+\seealso{_slang_version_string}
+\done
+
+\variable{_slang_version_string}
+\synopsis{The S-Lang library version number as a string}
+\usage{String_Type _slang_version_string}
+\description
+ The \var{_slang_version_string} variable is read-only and whose
+ value represents the version number of the \slang library.
+\seealso{_slang_version}
+\done
+
+\function{get_doc_string_from_file}
+\synopsis{Read documentation from a file}
+\usage{String_Type get_doc_string_from_file (String_Type f, String_Type t)}
+\description
+ \var{get_doc_string_from_file} opens the documentation file \var{f}
+ and searches it for topic \var{t}. It returns the documentation for
+ \var{t} upon success, otherwise it returns \var{NULL} upon error.
+ It will fail if \var{f} could not be opened or does not contain
+ documentation for the topic.
+\seealso{stat_file}
+\seealso{_slang_doc_dir}
+\done
+
+\function{is_defined}
+\synopsis{Indicate whether a variable or function defined.}
+\usage{Integer_Type is_defined (String_Type obj)}
+\description
+ This function is used to determine whether or not a function or
+ variable whose name is \var{obj} has been defined. If \var{obj} is not
+ defined, the function returns 0. Otherwise, it returns a non-zero
+ value that defpends on the type of object \var{obj} represents.
+ Specifically, it returns one of the following values:
+#v+
+ +1 if an intrinsic function
+ +2 if user defined function
+ -1 if intrinsic variable
+ -2 if user defined variable
+ 0 if undefined
+#v-
+\example
+ For example, consider the function:
+#v+
+ define runhooks (hook)
+ {
+ if (2 == is_defined(hook)) eval(hook);
+ }
+#v-
+ This function could be called from another \slang function to
+ allow customization of that function, e.g., if the function
+ represents a mode, the hook could be called to setup keybindings
+ for the mode.
+\seealso{typeof, eval, autoload, __get_reference, __is_initialized}
+\done
+
diff --git a/libslang/doc/tm/rtl/math.tm b/libslang/doc/tm/rtl/math.tm
new file mode 100644
index 0000000..104589f
--- /dev/null
+++ b/libslang/doc/tm/rtl/math.tm
@@ -0,0 +1,291 @@
+\function{Conj}
+\synopsis{Compute the complex conjugate of a number}
+\usage{z1 = Conj (z)}
+\description
+ The \var{Conj} function returns the complex conjugate of a number.
+ If its argument is an array, the \var{Conj} function will be applied to each
+ element and the result returned as an array.
+\seealso{Real, Imag, abs}
+\done
+
+\function{Imag}
+\synopsis{Compute the imaginary part of a number}
+\usage{i = Imag (z)}
+\description
+ The \var{Imag} function returns the imaginary part of a number.
+ If its argument is an array, the \var{Imag} function will be applied to each
+ element and the result returned as an array.
+\seealso{Real, Conj, abs}
+\done
+
+\function{Real}
+\synopsis{Compute the real part of a number}
+\usage{r = Real (z)}
+\description
+ The \var{Real} function returns the real part of a number. If its
+ argument is an array, the \var{Real} function will be applied to
+ each element and the result returned as an array.
+\seealso{Imag, Conj, abs}
+\done
+
+\function{abs}
+\synopsis{Compute the absolute value of a number}
+\usage{y = abs(x)}
+\description
+ The \var{abs} function returns the absolute value of an arithmetic
+ type. If its argument is a complex number (\var{Complex_Type}),
+ then it returns the modulus. If the argument is an array, a new
+ array will be created whose elements are obtained from the original
+ array by using the \var{abs} function.
+\seealso{sign, sqr}
+\done
+
+\function{acos}
+\synopsis{Compute the arc-cosine of an number}
+\usage{y = acos (x)}
+\description
+ The \var{acos} function computes the arc-cosine of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{acos} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{acosh}
+\synopsis{Compute the inverse cosh of an number}
+\usage{y = acosh (x)}
+\description
+ The \var{acosh} function computes the inverse cosh of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{acosh} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{asin}
+\synopsis{Compute the arc-sine of an number}
+\usage{y = asin (x)}
+\description
+ The \var{asin} function computes the arc-sine of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{asin} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{asinh}
+\synopsis{Compute the inverse-sinh of an number}
+\usage{y = asinh (x)}
+\description
+ The \var{asinh} function computes the inverse-sinh of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{asinh} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{atan}
+\synopsis{Compute the arc-tangent of an number}
+\usage{y = atan (x)}
+\description
+ The \var{atan} function computes the arc-tangent of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{atan} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{atanh}
+\synopsis{Compute the inverse-tanh of an number}
+\usage{y = atanh (x)}
+\description
+ The \var{atanh} function computes the inverse-tanh of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{atanh} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{cos}
+\synopsis{Compute the cosine of an number}
+\usage{y = cos (x)}
+\description
+ The \var{cos} function computes the cosine of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{cos} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{cosh}
+\synopsis{Compute the hyperbolic cosine of an number}
+\usage{y = cosh (x)}
+\description
+ The \var{cosh} function computes the hyperbolic cosine of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{cosh} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{exp}
+\synopsis{Compute the exponential of an number}
+\usage{y = exp (x)}
+\description
+ The \var{exp} function computes the exponential of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{exp} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{log}
+\synopsis{Compute the logarithm of an number}
+\usage{y = log (x)}
+\description
+ The \var{log} function computes the logarithm of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{log} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{log10}
+\synopsis{Compute the base-10 logarithm of an number}
+\usage{y = log10 (x)}
+\description
+ The \var{log10} function computes the base-10 logarithm of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{log10} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{mul2}
+\synopsis{Multiply a number by 2}
+\usage{y = mul2(x)}
+\description
+ The \var{mul2} function multiplies an arithmetic type by two and
+ returns the result. If its argument is an array, a new array will
+ be created whose elements are obtained from the original array by
+ using the \var{mul2} function.
+\seealso{sqr, abs}
+\done
+
+\function{polynom}
+\synopsis{Evaluate a polynomial}
+\usage{Double_Type polynom(Double_Type a, b, ...c, Integer_Type n, Double_Type x)}
+\description
+ The \var{polynom} function returns the value of the polynomial expression:
+#v+
+ ax^n + bx^(n - 1) + ... c
+#v-
+\notes
+ The \var{polynom} function should be extended to work with complex
+ and array data types. The current implementation is limited to
+ \var{Double_Type} quantities.
+\seealso{exp}
+\done
+
+\function{set_float_format}
+\synopsis{Set the format for printing floating point values.}
+\usage{set_float_format (String_Type fmt)}
+\description
+ The \var{set_float_format} function is used to set the floating
+ point format to be used when floating point numbers are printed.
+ The routines that use this are the traceback routines and the
+ \var{string} function. The default value is \exmp{"%f"}
+\example
+#v+
+ s = string (PI); % --> s = "3.14159"
+ set_float_format ("%16.10f");
+ s = string (PI); % --> s = "3.1415926536"
+ set_float_format ("%10.6e");
+ s = string (PI); % --> s = "3.141593e+00"
+#v-
+\seealso{string, sprintf, double}
+\done
+
+\function{sign}
+\synopsis{Compute the sign of a number}
+\usage{y = sign(x)}
+\description
+ The \var{sign} function returns the sign of an arithmetic type. If
+ its argument is a complex number (\var{Complex_Type}), it returns
+ the sign of the imaginary part of the number. If the argument is an
+ array, a new array will be created whose elements are obtained from
+ the original array by using the \var{sign} function.
+
+ When applied to a real number or an integer, the \var{sign} function
+ returns \-1, \0, or \exmp{+1} according to whether the number is
+ less than zero, equal to zero, or greater than zero, respectively.
+\seealso{abs}
+\done
+
+\function{sin}
+\synopsis{Compute the sine of an number}
+\usage{y = sin (x)}
+\description
+ The \var{sin} function computes the sine of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{sin} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{sinh}
+\synopsis{Compute the hyperbolic sine of an number}
+\usage{y = sinh (x)}
+\description
+ The \var{sinh} function computes the hyperbolic sine of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{sinh} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{sqr}
+\synopsis{Compute the square of a number}
+\usage{y = sqr(x)}
+\description
+ The \var{sqr} function returns the square of an arithmetic type. If its
+ argument is a complex number (\var{Complex_Type}), then it returns
+ the square of the modulus. If the argument is an array, a new array
+ will be created whose elements are obtained from the original array
+ by using the \var{sqr} function.
+\seealso{abs, mul2}
+\done
+
+\function{sqrt}
+\synopsis{Compute the square root of an number}
+\usage{y = sqrt (x)}
+\description
+ The \var{sqrt} function computes the square root of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{sqrt} function will be applied to each element and the result returned
+ as an array.
+\seealso{sqr, cos, atan, acosh, cosh}
+\done
+
+\function{tan}
+\synopsis{Compute the tangent of an number}
+\usage{y = tan (x)}
+\description
+ The \var{tan} function computes the tangent of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{tan} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
+\function{tanh}
+\synopsis{Compute the hyperbolic tangent of an number}
+\usage{y = tanh (x)}
+\description
+ The \var{tanh} function computes the hyperbolic tangent of a number and
+ returns the result as an array. If its argument is an array, the
+ \var{tanh} function will be applied to each element and the result returned
+ as an array.
+\seealso{cos, atan, acosh, cosh}
+\done
+
diff --git a/libslang/doc/tm/rtl/message.tm b/libslang/doc/tm/rtl/message.tm
new file mode 100644
index 0000000..e97f7cf
--- /dev/null
+++ b/libslang/doc/tm/rtl/message.tm
@@ -0,0 +1,111 @@
+\function{error}
+\synopsis{Generate an error condition}
+\usage{error (String_Type msg}
+\description
+ The \var{error} function generates a \slang error condition causing
+ the interpreter to start unwinding to top-level. It takes a single
+ string parameter which is displayed on the stderr output device.
+ The error condition may be cleared via an \var{ERROR_BLOCK} with the
+ \var{_clear_error} function. Consult \user-manual for more
+ information.
+\example
+#v+
+ define add_txt_extension (file)
+ {
+ if (typeof (file) != String_Type)
+ error ("add_extension: parameter must be a string");
+ file += ".txt";
+ return file;
+ }
+#v-
+\seealso{verror, _clear_error, message}
+\done
+
+\function{message}
+\synopsis{Print a string onto the message device}
+\usage{message (String_Type s}
+\description
+ The \var{message} function will print the string specified by
+ \var{s} onto the message device.
+\example
+#v+
+ define print_current_time ()
+ {
+ message (time ());
+ }
+#v-
+\notes
+ The message device will depend upon the application. For example,
+ the output message device for the \var{jed} editor correspond to the
+ line at the bottom of the display window. The default message
+ device is the standard output device.
+\seealso{vmessage, sprintf, error}
+\done
+
+\function{usage}
+\synopsis{Generate a usage error}
+\usage{usage (String_Type msg)}
+\description
+ The \var{usage} function generates a usage exception and displays
+ \var{msg} to the message device.
+\example
+ Suppose that some function \var{plot} plots an array of \var{x} and
+ \var{y} values. The such a function could be written to issue a
+ usage message if the wrong number of arguments were passed:
+#v+
+ define plot ()
+ {
+ variable x, y;
+
+ if (_NARGS != 2)
+ usage ("plot (x, y)");
+
+ (x, y) = ();
+ % Now do the hard part
+ .
+ .
+ }
+#v-
+\seealso{error, message}
+\done
+
+\function{verror}
+\synopsis{Generate an error condition}
+\usage{verror (String_Type fmt, ...)}
+\description
+ The \var{verror} function performs the same role as the \var{error}
+ function. The only difference is that instead of a single string
+ argument, \var{verror} takes a sprintf style argument list.
+\example
+#v+
+ define open_file (file)
+ {
+ variable fp;
+
+ fp = fopen (file, "r");
+ if (fp == NULL) verror ("Unable to open %s", file);
+ return fp;
+ }
+#v-
+\notes
+ In the current implementation, strictly speaking, the \var{verror}
+ function is not an intrinsic function. Rather it is a predefined
+ \slang function using a combination of \var{Sprintf} and
+ \var{error}.
+\seealso{error, Sprintf, vmessage}
+\done
+
+\function{vmessage}
+\synopsis{Print a formatted string onto the message device}
+\usage{vmessage (String_Type fmt, ...)}
+\description
+ The \var{vmessage} function formats a sprintf style argument list
+ and displays the resulting string onto the message device.
+\notes
+ In the current implementation, strictly speaking, the \var{vmessage}
+ function is not an intrinsic function. Rather it is a predefined
+ \slang function using a combination of \var{Sprintf} and
+ \var{message}.
+\seealso{message, Sprintf, verror}
+\done
+
diff --git a/libslang/doc/tm/rtl/misc.tm b/libslang/doc/tm/rtl/misc.tm
new file mode 100644
index 0000000..39cd62f
--- /dev/null
+++ b/libslang/doc/tm/rtl/misc.tm
@@ -0,0 +1,201 @@
+\function{__class_id}
+\synopsis{Return the class-id of a specified type}
+\usage{Int_Type __class_id (DataType_Type type))}
+\description
+ This function returns the internal class-id of a specified data type.
+\seealso{typeof, _typeof, __class_type}
+\done
+
+\function{__class_type}
+\synopsis{Return the class-type of a specified type}
+\usage{Int_Type __class_type (DataType_Type type))}
+\description
+ Internally \slang objects are classified according to four types:
+ scalar, vector, pointer, and memory managed types. For example, an
+ integer is implemented as a scalar, a complex number as a vector,
+ and a string is represented as a pointer. The \var{__class_type}
+ function returns an integer representing the class-type associated
+ with the specified data type. Specifically, it returns:
+#v+
+ 0 memory-managed
+ 1 scalar
+ 2 vector
+ 3 pointer
+#v-
+\seealso{typeof, _typeof, __class_id}
+\done
+
+\function{__eqs}
+\synopsis{Test for equality between two objects}
+\usage{Int_Type __eqs (a, b)}
+\description
+ This function tests its two arguments for equalit and returns \1
+ if they are equal, and \0 otherwise. To be equal, the data type of
+ the arguments must match and the values of the objects must
+ reference the same underlying object.
+\example
+ __eqs (1, 1) ===> 1
+ __eqs (1, 1.0) ===> 0
+ __eqs ("a", 1) ===> 0
+ __eqs ([1,2], [1,2]) ===> 0
+\seealso{typeof, __get_reference}
+\notes
+ This function should be thought of as a test for "sameness".
+\done
+
+\function{__get_reference}
+\synopsis{Get a reference to a global object}
+\usage{Ref_Type __get_reference (String_Type nm)}
+\description
+ This function returns a reference to a global variable or function
+ whose name is specified by \var{nm}. If no such object exists, it
+ returns \var{NULL}, otherwise it returns a reference.
+\example
+ For example, consider the function:
+#v+
+ define runhooks (hook)
+ {
+ variable f;
+ f = __get_reference (hook);
+ if (f != NULL)
+ @f ();
+ }
+#v-
+ This function could be called from another \slang function to
+ allow customization of that function, e.g., if the function
+ represents a mode, the hook could be called to setup keybindings
+ for the mode.
+\seealso{is_defined, typeof, eval, autoload, __is_initialized, __uninitialize}
+\done
+
+\function{__uninitialize}
+\synopsis{Uninitialize a variable}
+\usage{__uninitialize (Ref_Type x)}
+\description
+ The \var{__uninitialize} function may be used to uninitialize the
+ variable referenced by the parameter \var{x}.
+\example
+ The following two lines are equivalent:
+#v+
+ () = __tmp(z);
+ __uninitialize (&z);
+#v-
+\seealso{__tmp, __is_initialized}
+\done
+
+\variable{_auto_declare}
+\synopsis{Set automatic variable declaration mode}
+\usage{Integer_Type _auto_declare}
+\description
+ The \var{_auto_declare} may be used to have all undefined variables
+ implicitely declared as \var{static}. If set to zero, any variable
+ must be declared witha \var{variable} declaration before it can be
+ used. If set to one, then any undeclared variabled will be declared
+ as a \var{static} global variable.
+
+ The \var{_auto_declare} variable is local to each compilation unit and
+ setting its value in one unit has no effect upon its value in other
+ units. The value of this variable has no effect upon the variables
+ in a function.
+\example
+ The following code will not compile if \var{X} not been
+ declared:
+#v+
+ X = 1;
+#v-
+ However,
+#v+
+ _auto_declare = 1; % declare variables as static.
+ X = 1;
+#v-
+ is equivalent to
+#v+
+ static variable X = 1;
+#v-
+\notes
+ This variable should be used sparingly and is intended primarily for
+ interactive applications where one types \slang commands at a prompt.
+\done
+
+\function{current_namespace}
+\synopsis{Get the name of the current namespace}
+\usage{String_Type current_namespace ()}
+\description
+ The \var{current_namespace} function returns the name of the
+ current namespace. If the current namespace is anonymous, that is,
+ has not been given a name via the \var{implements} function, the
+ empty string \exmp{""} will be returned.
+\seealso{implements, use_namespace, import}
+\done
+
+\function{getenv}
+\synopsis{Get the value of an environment variable}
+\usage{String_Type getenv(String_Type var)}
+\description
+ The \var{getenv} function returns a string that represents the
+ value of an environment variable \var{var}. It will return
+ \var{NULL} if there is no environment variable whose name is given
+ by \var{var}.
+\example
+#v+
+ if (NULL != getenv ("USE_COLOR"))
+ {
+ set_color ("normal", "white", "blue");
+ set_color ("status", "black", "gray");
+ USE_ANSI_COLORS = 1;
+ }
+#v-
+\seealso{putenv, strlen, is_defined}
+\done
+
+\function{implements}
+\synopsis{Name a private namespace}
+\usage{implements (String_Type name);}
+\description
+ The \var{implements} function may be used to name the private
+ namespace associated with the current compilation unit. Doing so
+ will enable access to the members of the namespace from outside the
+ unit. The name of the global namespace is \exmp{Global}.
+\example
+ Suppose that some file \exmp{t.sl} contains:
+#v+
+ implements ("Ts_Private");
+ static define message (x)
+ {
+ Global->vmessage ("Ts_Private message: %s", x);
+ }
+ message ("hello");
+#v-
+ will produce \exmp{"Ts_Private message: hello"}. This \var{message}
+ function may be accessed from outside via:
+#v+
+ Ts_Private->message ("hi");
+#v-
+\notes
+ Since \var{message} is an intrinsic function, it is global and may
+ not be redefined in the global namespace.
+\seealso{use_namespace, current_namespace, import}
+\done
+
+\function{putenv}
+\synopsis{Add or change an environment variable}
+\usage{putenv (String_Type s)}
+\description
+ This functions adds string \var{s} to the environment. Typically,
+ \var{s} should of the form \var{"name=value"}. The function
+ signals a \slang error upon failure.
+\notes
+ This function is not available on all systems.
+\seealso{getenv, sprintf}
+\done
+
+\function{use_namespace}
+\synopsis{Change to another namespace}
+\usage{use_namespace (String_Type name)}
+\description
+ The \var{use_namespace} function changes the current namespace to
+ the one specified by the parameter. If the specified namespace
+ does not exist, an error will be generated.
+\seealso{implements, current_namespace, import}
+\done
+
diff --git a/libslang/doc/tm/rtl/ospath.tm b/libslang/doc/tm/rtl/ospath.tm
new file mode 100644
index 0000000..5604b8f
--- /dev/null
+++ b/libslang/doc/tm/rtl/ospath.tm
@@ -0,0 +1,77 @@
+\function{path_basename}
+\synopsis{Get the basename part of a pathname}
+\usage{String_Type path_basename (String_Type path)}
+\description
+ The \var{path_basename} function returns the basename associated
+ with the \var{path} parameter. The basename is the non-directory
+ part of the filename, e.g., on unix \exmp{c} is the basename of
+ \exmp{/a/b/c}.
+\seealso{path_dirname, path_extname, path_concat, path_is_absolute}
+\done
+
+\function{path_concat}
+\synopsis{Combine elements of a pathname}
+\usage{String_Type path_concat (String_Type dir, String_Type basename)}
+\description
+ The \var{path_concat} function combines the arguments \var{dir} and
+ \var{basename} to produce a pathname. For example, on unix is
+ \var{dir} is \exmp{x/y} and \var{basename} is \exmp{z}, then the
+ function will return \exmp{x/y/z}.
+\seealso{path_dirname, path_basename, path_extname, path_is_absolute}
+\done
+
+\function{path_dirname}
+\synopsis{Get the directory name part of a pathname}
+\usage{String_Type path_dirname (String_Type path)}
+\description
+ The \var{path_dirname} function returns the directory name
+ associated with a specified pathname.
+\notes
+ On systems that include a drive specifier as part of the pathname,
+ the value returned by this function will include the driver
+ specifier.
+\seealso{path_basename, path_extname, path_concat, path_is_absolute}
+\done
+
+\function{path_extname}
+\synopsis{Return the extension part of a pathname}
+\usage{String_Type path_extname (String_Type path)}
+\description
+ The \var{path_extname} function returns the extension portion of a
+ specified pathname. If an extension is present, this function will
+ also include the dot as part of the extension, i.e., if \var{path}
+ is \exmp{file.c}, then this function returns \exmp{".c"}. If no
+ extension is present, the function returns an empty string \exmp{""}.
+\notes
+ Under VMS, the file version number is not returned as part of the
+ extension.
+\seealso{path_sans_extname, path_dirname, path_basename, path_concat, path_is_absolute}
+\done
+
+\function{path_get_delimiter}
+\synopsis{Get the value of a search-path delimiter}
+\usage{Char_Type path_get_delimiter ()}
+\description
+ This function returns the value of the character used to delimit
+ fields of a search-path.
+\seealso{set_slang_load_path, get_slang_load_path}
+\done
+
+\function{path_is_absolute}
+\synopsis{Determine whether or not a pathname is absolute}
+\usage{Int_Type path_is_absolute (String_Type path)}
+\description
+ The \var{path_is_absolute} function will return non-zero is
+ \var{path} refers to an absolute pathname, otherwise it returns zero.
+\seealso{path_dirname, path_basename, path_extname, path_concat}
+\done
+
+\function{path_sans_extname}
+\synopsis{Strip the extension from a pathname}
+\usage{String_Type path_sans_extname (String_Type path)}
+\description
+ The \var{path_sans_extname} function removes the file name extension
+ (including the dot) from the path and returns the result.
+\seealso{path_extname, path_basename, path_dirname, path_concat}
+\done
+
diff --git a/libslang/doc/tm/rtl/posio.tm b/libslang/doc/tm/rtl/posio.tm
new file mode 100644
index 0000000..cb7bc40
--- /dev/null
+++ b/libslang/doc/tm/rtl/posio.tm
@@ -0,0 +1,154 @@
+\function{close}
+\synopsis{Close an open file descriptor}
+\usage{Int_Type close (FD_Type fd)}
+\description
+ The \var{close} function is used to open file descriptor of type
+ \var{FD_Type}. Upon success \0 is returned, otherwise the function
+ returns \-1 and sets \var{errno} accordingly.
+\seealso{open, fclose, read, write}
+\done
+
+\function{dup_fd}
+\synopsis{Duplicate a file descriptor}
+\usage{FD_Type dup_fd (FD_Type fd)}
+\description
+ The \var{dup_fd} function duplicates and file descriptor and returns
+ its duplicate. If the function fails, \NULL will be returned and
+ \var{errno} set accordingly.
+\notes
+ This function is essentually a wrapper around the POSIX \var{dup}
+ function.
+\seealso{open, close}
+\done
+
+\function{fileno}
+\synopsis{Convert a stdio File_Type object to a FD_Type descriptor}
+\usage{FD_Type fileno (File_Type fp)}
+\description
+ The \var{fileno} function returns the \var{FD_Type} descriptor
+ associated with the \var{File_Type} file pointer. Upon failure,
+ \NULL is returned.
+\seealso{fopen, open, fclose, close, dup_fd}
+\done
+
+\function{isatty}
+\synopsis{Determine if an open file descriptor refers to a terminal}
+\usage{Int_Type isatty (FD_Type or File_Type fd)}
+\description
+ This function returns \1 if the file descriptor \var{fd} refers to a
+ terminal; otherwise it returns \0. The object \var{fd} may either
+ be a \var{File_Type} stdio descriptor or an \var{FD_Type} object.
+\seealso{fopen, fclose, fileno}
+\done
+
+\function{lseek}
+\synopsis{Reposition a file descriptor's file pointer}
+\usage{Long_Type lseek (FD_Type fd, Long_Type ofs, int mode)}
+ The \var{lseek} function repositions the file pointer associated
+ with the open file descriptor \var{fp} to offset \var{ofs}
+ according to the mode parameter. Specifically, \var{mode} must be
+ one of the values:
+#v+
+ SEEK_SET Set the offset to ofs
+ SEEK_CUR Add ofs to the current offset
+ SEEK_END Add ofs to the current file size
+#v-
+ Upon error, \var{lseek} returns \-1 and sets \var{errno}. If
+ successful, it returns the new filepointer offset.
+\notes
+ Not all file descriptors are capable of supporting the seek
+ operation, e.g., a descriptor associated with a pipe.
+
+ By using \var{SEEK_END} with a positive value of the \var{ofs}
+ parameter, it is possible to position the file pointer beyond the
+ current size of the file.
+\seealso{fseek, ftell, open, close}
+\done
+
+\function{open}
+\synopsis{Open a file}
+\usage{FD_Type open (String_Type filename, Int_Type flags [,Int_Type mode])}
+\description
+ The \var{open} function attempts to open a file specified by the
+ \var{filename} parameter according to the \var{flags} parameter,
+ which must be one of the following values:
+#v+
+ O_RDONLY (read-only)
+ O_WRONLY (write-only)
+ O_RDWR (read/write)
+#v-
+ In addition, \var{flags} may also be bitwise-or'd with any of the
+ following:
+#v+
+ O_BINARY (open the file in binary mode)
+ O_TEXT (open the file in text mode)
+ O_CREAT (create file if it does not exist)
+ O_EXCL (fail if the file already exists)
+ O_NOCTTY (do not make the device the controlling terminal)
+ O_TRUNC (truncate the file if it exists)
+ O_APPEND (open the file in append mode)
+ O_NONBLOCK (open the file in non-blocking mode)
+#v-
+ Some of these flags only make sense when combined with other flags.
+ For example, if O_EXCL is used, then O_CREAT must also be
+ specified, otherwise unpredictable behavior may result.
+
+ If \var{O_CREAT} is used for the \var{flags} parameter then the
+ \var{mode} parameter must be present. \var{mode} specifies the
+ permissions to use if a new file is created. The actual file
+ permissions will be affected by the process's \var{umask} via
+ \exmp{mode&~umask}. The \var{mode} parameter's value is
+ constructed via bitwise-or of the following values:
+#v+
+ S_IRWXU (Owner has read/write/execute permission)
+ S_IRUSR (Owner has read permission)
+ S_IWUSR (Owner has write permission)
+ S_IXUSR (Owner has execute permission)
+ S_IRWXG (Group has read/write/execute permission)
+ S_IRGRP (Group has read permission)
+ S_IWGRP (Group has write permission)
+ S_IXGRP (Group has execute permission)
+ S_IRWXO (Others have read/write/execute permission)
+ S_IROTH (Others have read permission)
+ S_IWOTH (Others have write permission)
+ S_IXOTH (Others have execute permission)
+#v-
+ Upon success \var{open} returns a file descriptor object
+ (\var{FD_Type}), otherwise \var{NULL} is returned and \var{errno}
+ is set.
+\notes
+ If you are not familiar with the \var{open} system call, then it
+ is recommended that you use \var{fopen} instead.
+\seealso{fopen, close, read, write, stat_file}
+\done
+
+\function{read}
+\synopsis{Read from an open file descriptor}
+\usage{UInt_Type read (FD_Type fd, Ref_Type buf, UInt_Type num)}
+\description
+ The \var{read} function attempts to read at most \var{num} bytes
+ into the variable indicated by \var{buf} from the open file
+ descriptor \var{fd}. It returns the number of bytes read, or \-1
+ and sets \var{errno} upon failure. The number of bytes read may be
+ less than \var{num}, and will be zero if an attempt is made to read
+ past the end of the file.
+\notes
+ \var{read} is a low-level function and may return \-1 for a variety
+ of reasons. For example, if non-blocking I/O has been specified for
+ the open file descriptor and no data is available for reading then
+ the function will return \-1 and set \var{errno} to \var{EAGAIN}.
+\seealso{fread, open, close, write}
+\done
+
+\function{write}
+\synopsis{Write to an open file descriptor}
+\usage{UInt_Type write (FD_Type fd, BString_Type buf)}
+\description
+ The \var{write} function attempts to write the bytes specified by
+ the \var{buf} parameter to the open file descriptor \var{fd}. It
+ returns the number of bytes successfully written, or \-1 and sets
+ \var{errno} upon failure. The number of bytes written may be less
+ than \exmp{length(buf)}.
+\seealso{read, fwrite, open, close}
+\done
+
diff --git a/libslang/doc/tm/rtl/posix.tm b/libslang/doc/tm/rtl/posix.tm
new file mode 100644
index 0000000..d16b6eb
--- /dev/null
+++ b/libslang/doc/tm/rtl/posix.tm
@@ -0,0 +1,285 @@
+\variable{errno}
+\synopsis{Error code set by system functions.}
+\usage{Integer_Type errno}
+\description
+ A system function can fail for a variety of reasons. For example, a
+ file operation may fail because lack of disk space, or the process
+ does not have permission to perform the operation. Such functions
+ will return \var{-1} and set the variable \var{errno} to an error
+ code describing the reason for failure.
+
+ Particular values of \var{errno} may be specified by the following
+ symbolic constants (read-only variables) and the corresponding
+ \var{errno_string} value:
+#v+
+ EPERM "Not owner"
+ ENOENT "No such file or directory"
+ ESRCH "No such process"
+ ENXIO "No such device or address"
+ ENOEXEC "Exec format error"
+ EBADF "Bad file number"
+ ECHILD "No children"
+ ENOMEM "Not enough core"
+ EACCES "Permission denied"
+ EFAULT "Bad address"
+ ENOTBLK "Block device required"
+ EBUSY "Mount device busy"
+ EEXIST "File exists"
+ EXDEV "Cross-device link"
+ ENODEV "No such device"
+ ENOTDIR "Not a directory"
+ EISDIR "Is a directory"
+ EINVAL "Invalid argument"
+ ENFILE "File table overflow"
+ EMFILE "Too many open files"
+ ENOTTY "Not a typewriter"
+ ETXTBSY "Text file busy"
+ EFBIG "File too large"
+ ENOSPC "No space left on device"
+ ESPIPE "Illegal seek"
+ EROFS "Read-only file system"
+ EMLINK "Too many links"
+ EPIPE "Broken pipe"
+ ELOOP "Too many levels of symbolic links"
+ ENAMETOOLONG "File name too long"
+#v-
+\example
+ The \var{mkdir} function will attempt to create a directory. If
+ that directory already exists, the function will fail and set
+ \var{errno} to \var{EEXIST}.
+#v+
+ define create_dir (dir)
+ {
+ if (0 == mkdir (dir)) return;
+ if (errno != EEXIST)
+ error ("mkdir %s failied: %s", dir, errno_string);
+ }
+#v-
+\seealso{errno_string, error, mkdir}
+\done
+
+\function{errno_string}
+\synopsis{Return a string describing an errno.}
+\usage{String_Type errno_string (Integer_Type err)}
+\description
+ The \var{errno_string} function returns a string describing the
+ integer error code \var{err}. The variable \var{err} usually
+ corresponds to the \var{errno} intrinsic function. See the
+ description for \var{errno} for more information.
+\example
+ The \var{errno_string} function may be used as follows:
+#v+
+ define sizeof_file (file)
+ {
+ variable st = stat (file);
+ if (st == NULL)
+ verror ("%s: %s", file, errno_string (errno);
+ return st.st_size;
+ }
+#v-
+\seealso{errno, stat, verror}
+\done
+
+\function{getegid}
+\synopsis{Get the effective group id}
+\usage{Int_Type getegid ()}
+\description
+ The \var{getegid} function returns the effective group ID of the
+ current process.
+\notes
+ This function is not supported by all systems.
+\seealso{getgid, geteuid, setgid}
+\done
+
+\function{geteuid}
+\synopsis{Get the effective user-id of the current process}
+\usage{Int_Type geteuid ()}
+\description
+ The \var{geteuid} function returns the effective user-id of the
+ current process.
+\notes
+ This function is not supported by all systems.
+\seealso{getuid, setuid, setgid}
+\done
+
+\function{getgid}
+\synopsis{Get the group id}
+\usage{Integer_Type getgid ()}
+\description
+ The \var{getgid} function returns the real group id of the current
+ process.
+\notes
+ This function is not supported by all systems.
+\seealso{getpid, getppid}
+\done
+
+\function{getpid}
+\synopsis{Get the current process id}
+\usage{Integer_Type getpid ()}
+\description
+ The \var{getpid} function returns the current process identification
+ number.
+\seealso{getppid, getgid}
+\done
+
+\function{getppid}
+\synopsis{Get the parent process id}
+\usage{Integer_Type getppid ()}
+\description
+ The \var{getpid} function returns the process identification
+ number of the parent process.
+\notes
+ This function is not supported by all systems.
+\seealso{getpid, getgid}
+\done
+
+\function{getuid}
+\synopsis{Get the user-id of the current process}
+\usage{Int_Type getuid ()}
+\description
+ The \var{getuid} function returns the user-id of the current
+ process.
+\notes
+ This function is not supported by all systems.
+\seealso{getuid, getegid}
+\done
+
+\function{kill}
+\synopsis{Send a signal to a process}
+\usage{Integer_Type kill (Integer_Type pid, Integer_Type sig)}
+\description
+ This function may be used to send a signal given by the integer \var{sig}
+ to the process specified by \var{pid}. The function returns zero upon
+ success and \exmp{-1} upon failure setting errno accordingly.
+\example
+ The \var{kill} function may be used to determine whether or not
+ a specific process exists:
+#v+
+ define process_exists (pid)
+ {
+ if (-1 == kill (pid, 0))
+ return 0; % Process does not exist
+ return 1;
+ }
+#v-
+\notes
+ This function is not supported by all systems.
+\seealso{getpid}
+\done
+
+\function{mkfifo}
+\synopsis{Create a named pipe}
+\usage{Int_Type mkfifo (String_Type name, Int_Type mode)}
+\description
+ The \var{mkfifo} attempts to create a named pipe with the specified
+ name and mode (modified by the process's umask). The function
+ returns \0 upon success, or \-1 and sets \var{errno} upon failure.
+\notes
+ Not all systems support the \var{mkfifo} function and even on
+ systems that do implement the \var{mkfifo} system call, the
+ underlying file system may not support the concept of a named pipe,
+ e.g, an NFS filesystem.
+\seealso{stat_file}
+\done
+
+\function{setgid}
+\synopsis{Set the group-id of the current process}
+\usage{Int_Type setgid (Int_Type gid)}
+\description
+ The \var{setgid} function sets the effective group-id of the current
+ process. It returns zero upon success, or \-1 upon error and sets
+ \var{errno} appropriately.
+\notes
+ This function is not supported by all systems.
+\seealso{getgid, setuid}
+\done
+
+\function{setpgid}
+\synopsis{Set the process group-id}
+\usage{Int_Type setpgid (Int_Type pid, Int_Type gid)}
+\description
+ The \var{setpgid} function sets the group-id \var{gid} of the
+ process whose process-id is \var{pid}. If \var{pid} is \0, then the
+ current process-id will be used. If \var{pgid} is \0, then the pid
+ of the affected process will be used.
+
+ If successful zero will be returned, otherwise the function will
+ return \-1 and set \var{errno} accordingly.
+\notes
+ This function is not supported by all systems.
+\seealso{setgid, setuid}
+\done
+
+\function{setuid}
+\synopsis{Set the user-id of the current process}
+\usage{Int_Type setuid (Int_Type id)}
+\description
+ The \var{setuid} function sets the effective user-id of the current
+ process. It returns zero upon success, or \-1 upon error and sets
+ \var{errno} appropriately.
+\notes
+ This function is not supported by all systems.
+\seealso{setgid, setpgid, getuid, geteuid}
+\done
+
+\function{sleep}
+\synopsis{Pause for a specified number of seconds}
+\usage{sleep (Double_Type n)}
+\description
+ The \var{sleep} function delays the current process for the
+ specified number of seconds. If it is interrupted by a signal, it
+ will return prematurely.
+\notes
+ Not all system support sleeping for a fractional part of a second.
+\done
+
+\function{system}
+\synopsis{Execute a shell command}
+\usage{Integer_Type system (String_Type cmd)}
+\description
+ The \var{system} function may be used to execute the string
+ expression \var{cmd} in an inferior shell. This function is an
+ interface to the C \var{system} function which returns an
+ implementation-defined result. On Linux, it returns 127 if the
+ inferior shell could not be invoked, -1 if there was some other
+ error, otherwise it returns the return code for \var{cmd}.
+\example
+#v+
+ define dir ()
+ {
+ () = system ("DIR");
+ }
+#v-
+ displays a directory listing of the current directory under MSDOS or
+ VMS.
+\seealso{popen, listdir}
+\done
+
+\function{umask}
+\synopsis{Set the file creation mask}
+\usage{Int_Type umask (Int_Type m)}
+\description
+ The \var{umask} function sets the file creation mask to \var{m} and
+ returns the previous mask.
+\seealso{stat_file}
+\done
+
+\function{uname}
+\synopsis{Get the system name}
+\usage{Struct_Tye uname ()}
+\description
+ The \var{uname} function returns a structure containing information
+ about the operating system. The structure contains the following
+ fields:
+#v+
+ sysname (Name of the operating system)
+ nodename (Name of the node within the network)
+ release (Release level of the OS)
+ version (Current version of the release)
+ machine (Name of the hardware)
+#v-
+\notes
+ Not all systems support this function.
+\seealso{getenv, pack, unpack}
+\done
+
diff --git a/libslang/doc/tm/rtl/stack.tm b/libslang/doc/tm/rtl/stack.tm
new file mode 100644
index 0000000..ad00a71
--- /dev/null
+++ b/libslang/doc/tm/rtl/stack.tm
@@ -0,0 +1,165 @@
+\function{__pop_args}
+\synopsis{Remove n function arguments from the stack}
+\usage{variable args = __pop_args(Integer_Type n);}
+\description
+ This function together with the companion function \var{__push_args}
+ is useful for passing the arguments of a function to another function.
+ \var{__pop_args} returns an array of \var{n} structures with a
+ single structure field called \var{value}, which represents the value
+ of the argument.
+\example
+ Consider the following \var{print} function. It prints all its
+ arguments to \var{stdout} separated by spaces:
+#v+
+ define print ()
+ {
+ variable i;
+ variable args = __pop_args (_NARGS);
+
+ for (i = 0; i < _NARGS; i++)
+ {
+ () = fputs (string (args[i].value), stdout);
+ () = fputs (" ", stdout);
+ }
+ () = fputs ("\n", stdout);
+ () = fflush (stdout);
+ }
+#v-
+ Now consider the problem of defining a function called \var{ones}
+ that returns a multi-dimensional array with all the elements set to
+ 1. For example, \exmp{ones(10)} should return a 1-d array of ones,
+ whereas \exmp{ones(10,20)} should return a 10x20 array.
+#v+
+ define ones ()
+ {
+ !if (_NARGS) return 1;
+ variable a;
+
+ a = __pop_args (_NARGS);
+ return @Array_Type (Integer_Type, [__push_args (a)]) + 1;
+ }
+#v-
+ Here, \var{__push_args} was used to push on the arguments passed to
+ the \var{ones} function onto the stack to be used when dereferencing
+ \var{Array_Type}.
+\seealso{__push_args, typeof, _pop_n}
+\done
+
+\function{__push_args}
+\synopsis{Remove n function arguments onto the stack}
+\usage{__push_args (Struct_Type args);}
+\description
+ This function together with the companion function \var{__pop_args}
+ is useful for passing the arguments of one function to another.
+ See the desription of \var{__pop_args} for more information.
+\seealso{__pop_args, typeof, _pop_n}
+\done
+
+\function{_pop_n}
+\synopsis{Remove objects from the stack}
+\usage{_pop_n (Integer_Type n);}
+\description
+ The \var{_pop_n} function pops \var{n} objects from the top of the
+ stack.
+\example
+#v+
+ define add3 ()
+ {
+ variable x, y, z;
+ if (_NARGS != 3)
+ {
+ _pop_n (_NARGS);
+ error ("add3: Expecting 3 arguments");
+ }
+ (x, y, z) = ();
+ return x + y + z;
+ }
+#v-
+\seealso{_stkdepth, pop}
+\done
+
+\function{_print_stack}
+\synopsis{print the values on the stack.}
+\usage{_print_stack ()}
+\description
+ This function dumps out what is currently on the \slang. It does not
+ alter the stack and it is usually used for debugging purposes.
+\seealso{_stkdepth, string}
+\done
+
+\function{_stk_reverse}
+\synopsis{Reverse the order of the objects on the stack.}
+\usage{_stk_reverse (Integer_Type n)}
+\description
+ The \var{_stk_reverse} function reverses the order of the top
+ \var{n} items on the stack.
+\seealso{_stkdepth, _stk_roll}
+\done
+
+\function{_stk_roll}
+\synopsis{Roll items on the stack}
+\usage{_stk_roll (Integer_Type n);}
+\description
+ This function may be used to alter the arrangement of objects on the
+ stack. Specifically, if the integer \var{n} is positive, the top
+ \var{n} items on the stack are rotated up. If
+ \var{n} is negative, the top \var{abs(n)} items on the stack are
+ rotated down.
+\example
+ If the stack looks like:
+#v+
+ item-0
+ item-1
+ item-2
+ item-3
+#v-
+ where \exmp{item-0} is at the top of the stack, then
+ \exmp{_stk_roll(-3)} will change the stack to:
+#v+
+ item-2
+ item-0
+ item-1
+ item-3
+#v-
+\notes
+ This function only has an effect for \exmp{abs(n) > 1}.
+\seealso{_stkdepth, _stk_reverse, _pop_n, _print_stack}
+\done
+
+\function{_stkdepth}
+\usage{Get the number of objects currently on the stack.}
+\synopsis{Integer_Type _stkdepth ()}
+\description
+ The \var{_stkdepth} function returns number of items on stack prior
+ to the call of \var{_stkdepth}.
+\seealso{_print_stack, _stk_reverse, _stk_roll}
+\done
+
+\function{dup}
+\synopsis{Duplicate the value at the top of the stack}
+\usage{dup ()}
+\description
+ This function returns an exact duplicate of the object on top of the
+ stack. For some objects such as arrays or structures, it creates a
+ new reference to the array. However, for simple scalar S-Lang types such
+ as strings, integers, and doubles, it creates a new copy of the
+ object.
+\seealso{pop, typeof}
+\done
+
+\function{exch}
+\synopsis{Exchange two items on the stack}
+\usage{exch ()}
+\description
+ The \var{exch} swaps the two top items on the stack.
+\seealso{pop, _stk_reverse, _stk_roll}
+\done
+
+\function{pop}
+\synopsis{Discard an item from the stack}
+\usage{pop ()}
+\description
+ The \var{pop} function removes the top item from the stack.
+\seealso{_pop_n}
+\done
+
diff --git a/libslang/doc/tm/rtl/stdio.tm b/libslang/doc/tm/rtl/stdio.tm
new file mode 100644
index 0000000..abb5ea8
--- /dev/null
+++ b/libslang/doc/tm/rtl/stdio.tm
@@ -0,0 +1,421 @@
+\function{clearerr}
+\synopsis{Clear the error of a file stream}
+\usage{clearerr (File_Type fp}
+\description
+ The \var{clearerr} function clears the error and end-of-file flags
+ associated with the open file stream \var{fp}.
+\seealso{ferror, feof, fopen}
+\done
+
+\function{fclose}
+\synopsis{Close a file}
+\usage{Integer_Type fclose (File_Type fp)}
+\description
+ The \var{fclose} function may be used to close an open file pointer
+ \var{fp}. Upon success it returns zero, and upon failure it sets
+ \var{errno} and returns \exmp{-1}. Failure usually indicates a that
+ the file system is full or that \var{fp} does not refer to an open file.
+\notes
+ Many C programmers call \var{fclose} without checking the return
+ value. The \slang language requires the programmer to explicitly
+ handle any value returned by a \slang function. The simplest way to
+ handle the return value from \var{fclose} is to use it as:
+#v+
+ () = fclose (fp);
+#v-
+\seealso{fopen, fgets, fflush, pclose, errno}
+\done
+
+\function{fdopen}
+\synopsis{Convert a FD_Type file descriptor to a stdio File_Type object}
+\usage{File_Type fdopen (FD_Type, String_Type mode)}
+\description
+ The \var{fdopen} function creates and returns a stdio
+ \var{File_Type} object from the open \var{FD_Type}
+ descriptor \var{fd}. The \var{mode} parameter corresponds to the
+ \var{mode} parameter of the \var{fopen} function and must be
+ consistent with the mode of the descriptor \var{fd}. The function
+ returns \NULL upon failure and sets \var{errno}.
+\notes
+ The \var{fclose} function does not close the \var{File_Type} object
+ returned from this function. The underlying file object must be
+ closed by the \var{close} function.
+\seealso{fileno, fopen, open, close, fclose}
+\done
+
+\function{feof}
+\synopsis{Get the end-of-file status}
+\usage{Integer_Type feof (File_Type fp)}
+\description
+ This function may be used to determine the state of the end-of-file
+ indicator of the open file descriptor \var{fp}. It returns \var{0}
+ if the indicator is not set, or non-zero if it is. The end-of-file
+ indicator may be cleared by the \var{clearerr} function.
+\seealso{ferror, clearerr, fopen}
+\done
+
+\function{ferror}
+\synopsis{Determine the error status of an open file descriptor}
+\usage{Integer_Type ferror (File_Type fp)}
+\description
+ This function may be used to determine the state of the error
+ indicator of the open file descriptor \var{fp}. It returns \var{0}
+ if the indicator is not set, or non-zero if it is. The error
+ indicator may be cleared by the \var{clearerr} function.
+\seealso{feof, clearerr, fopen}
+\done
+
+\function{fflush}
+\synopsis{Flush an output stream}
+\usage{Integer_Type fflush (File_Type fp)}
+\description
+ The \var{fflush} function may be used to update the \em{output}
+ stream specified by \var{fp}. It returns \var{0} upon success, or
+ \var{-1} upon failure and sets \var{errno} accordingly. In
+ particular, this function will fail if \var{fp} does not represent
+ an output stream, or if \var{fp} is associated with a disk file and
+ there is insufficient disk space.
+\example
+ This example illustrates how to use the \var{fflush} function
+ without regard to the return value:
+#v+
+ () = fputs ("Enter value> ", stdout);
+ () = fflush (stdout);
+#v-
+\notes
+ Many C programmers disregard the return value from the \var{fflush}
+ function. The above example illustrates how to properly do this in
+ the \slang langauge.
+\seealso{fopen, fclose}
+\done
+
+\function{fgets}
+\synopsis{Read a line from a file.}
+\usage{Integer_Type fgets (SLang_Ref_Type ref, File_Type fp)}
+\description
+ \var{fgets} reads a line from the open file specified by \var{fp}
+ and places the characters in the variable whose reference is
+ specified by \var{ref}.
+ It returns \exmp{-1} if \var{fp} is not associated with an open file
+ or an attempt was made to read at the end the file; otherwise, it
+ returns the number of characters read.
+\example
+ The following example returns the lines of a file via a linked list:
+#v+
+ define read_file (file)
+ {
+ variable buf, fp, root, tail;
+ variable list_type = struct { text, next };
+
+ root = NULL;
+
+ fp = fopen(file, "r");
+ if (fp == NULL)
+ error("fopen %s failed." file);
+ while (-1 != fgets (&buf, fp))
+ {
+ if (root == NULL)
+ {
+ root = @list_type;
+ tail = root;
+ }
+ else
+ {
+ tail.next = @list_type;
+ tail = tail.next;
+ }
+ tail.text = buf;
+ tail.next = NULL;
+ }
+ () = fclose (fp);
+ return root;
+ }
+#v-
+\seealso{fopen, fclose, fputs, fread, error}
+\done
+
+\function{fgetslines}
+\synopsis{Read all the lines from an open file}
+\usage{String_Type[] fgetslines (File_Type fp)}
+\description
+ The \var{fgetslines} function returns all the remaining lines as an
+ array of strings in the file specified by the open file pointer
+ \var{fp}. If the file is empty, an empty string array will be
+ returned. The function returns \var{NULL} upon error.
+\example
+ The following function returns the number of lines in a file:
+#v+
+ define count_lines_in_file (file)
+ {
+ variable fp, lines;
+
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ return -1;
+
+ lines = fgetslines (fp);
+ if (lines == NULL)
+ return -1;
+
+ return length (lines);
+ }
+#v-
+ Note that the file was implicitly closed by the function.
+\notes
+ This function should not be used if the file contains many lines
+ since that would require that all the lines be read into memory.
+\seealso{fgets, fread, fopen}
+\done
+
+\function{fopen}
+\synopsis{Open a file}
+\usage{File_Type fopen (String_Type f, String_Type m)}
+\description
+ The \var{fopen} function opens a file \var{f} according to the mode
+ string \var{m}. Allowed values for \var{m} are:
+#v+
+ "r" Read only
+ "w" Write only
+ "a" Append
+ "r+" Reading and writing at the beginning of the file.
+ "w+" Reading and writing. The file is created if it does not
+ exist; otherwise, it is truncated.
+ "a+" Reading and writing at the end of the file. The file is created
+ if it does not already exist.
+#v-
+ In addition, the mode string can also include the letter \var{'b'}
+ as the last character to indicate that the file is to be opened in
+ binary mode.
+
+ Upon success, \var{fopen} a \var{File_Type} object which is meant to
+ be used in other operations that require an open file. Upon
+ failure, the function returns \var{NULL}.
+\example
+ The following function opens a file in append mode and writes a
+ string to it:
+#v+
+ define append_string_to_file (file, str)
+ {
+ variable fp = fopen (file, "a");
+ if (fp == NULL) verror ("%s could not be opened", file);
+ () = fputs (string, fp);
+ () = fclose (fp);
+ }
+#v-
+ Note that the return values from \var{fputs} and \var{fclose} are
+ ignored.
+\notes
+ There is no need to explicitly close a file opened with \var{fopen}.
+ If the returned \var{File_Type} object goes out of scope, \slang
+ will automatically close the file. However, explicitly closing a
+ file after use is recommended.
+\seealso{fclose, fgets, fputs, popen}
+\done
+
+\function{fprintf}
+\synopsis{Create and write a formatted string to a file}
+\usage{Int_Type fprintf (File_Type fp, String_Type fmt, ...)}
+\description
+ \var{fprintf} formats the objects specified by the variable argument
+ list according to the format \var{fmt} and write the result to the
+ open file pointer \var{fp}.
+
+ The format string obeys the same syntax and semantics as the
+ \var{sprintf} format string. See the description of the
+ \var{sprintf} function for more information.
+
+ \var{fprintf} returns the number of characters written to the file,
+ or \-1 upon error.
+\seealso{fputs, printf, fwrite, message}
+\done
+
+\function{fputs}
+\synopsis{Write a string to an open stream}
+\usage{Integer_Type fputs (String_Type s, File_Type fp);}
+\description
+ The \var{fputs} function writes the string \var{s} to the open file
+ pointer \var{fp}. It returns -1 upon failure and sets \var{errno},
+ otherwise it returns the length of the string.
+\example
+ The following function opens a file in append mode and uses the
+ \var{fputs} function to write to it.
+#v+
+ define append_string_to_file (str, file)
+ {
+ variable fp;
+ fp = fopen (file, "a");
+ if (fp == NULL) verror ("Unable to open %s", file);
+ if ((-1 == fputs (s, fp))
+ or (-1 == fclose (fp)))
+ verror ("Error writing to %s", file);
+ }
+#v-
+\notes
+ One must not disregard the return value from the \var{fputs}
+ function, as many C programmers do. Doing so may lead to a stack
+ overflow error.
+
+ To write an object that contains embedded null characters, use the
+ \var{fwrite} function.
+\seealso{fclose, fopen, fgets, fwrite}
+\done
+
+\function{fread}
+\synopsis{Read binary data from a file}
+\usage{UInt_Type fread (Ref_Type b, DataType_Type t, UInt_Type n, File_Type fp)}
+\description
+ The \var{fread} function may be used to read \var{n} objects of type
+ \var{t} from an open file pointer \var{fp}. Upon success, it
+ returns the number of objects read from the file and places the
+ objects in the variable specified by \var{b}. Upon error or end of
+ file, it returns \var{-1}. If more than one object is read from the
+ file, those objects will be placed in an array of the appropriate
+ size. The exception to this is when reading \var{Char_Type} or
+ \var{UChar_Type} objects from a file, in which case the data will be
+ returned as an \var{n} character BString_Type binary string, but
+ only if \var{n}>1.
+\example
+ The following example illustrates how to read 50 bytes from a file:
+#v+
+ define read_50_bytes_from_file (file)
+ {
+ variable fp, n, buf;
+
+ fp = fopen (file, "rb");
+ if (fp == NULL) error ("Open failed");
+ n = fread (&buf, Char_Type, 50, fp);
+ if (n == -1)
+ error ("fread failed");
+ () = fclose (fp);
+ return buf;
+ }
+#v-
+\notes
+ Use the \var{pack} and \var{unpack} functions to read data with a
+ specific byte-ordering.
+\seealso{fwrite, fgets, fopen, pack, unpack}
+\done
+
+\function{fseek}
+\synopsis{Reposition a stream}
+\usage{Integer_Type fseek (File_Type fp, Integer_Type ofs, Integer_Type whence}
+\description
+ The \var{fseek} function may be used to reposition the file position
+ pointer associated with the open file stream \var{fp}. Specifically,
+ it moves the pointer \var{ofs} bytes relative to the position
+ indicated by \var{whence}. If whence is set to one of the symbolic
+ constants \exmp{SEEK_SET}, \exmp{SEEK_CUR}, or \exmp{SEEK_END}, the
+ offset is relative to the start of the file, the current position
+ indicator, or end-of-file, respectively.
+
+ The function return zero upon success, or \-1 upon failure and sets
+ \var{errno} accordingly.
+\example
+ define rewind (fp)
+ {
+ if (0 == fseek (fp, 0, SEEK_SET)) return;
+ vmessage ("rewind failed, reason: %s", errno_string (errno));
+ }
+\notes
+ The current implementation uses an integer to specify the offset.
+ One some systems, a long integer may be required making this
+ function fail for very large files, i.e., files that are longer than
+ the maximum value of an integer.
+\seealso{ftell, fopen}
+\done
+
+\function{ftell}
+\synopsis{Obtain the current position in an open stream}
+\usage{Integer_Type ftell (File_Type fp)}
+\description
+ The ftell function may be used to obtain the current position in the
+ stream associated with the open file pointer \var{fp}. It returns
+ the position of the pointer measured in bytes from the beginning of
+ the file. Upon error, it returns \exmp{-1} and sets \var{errno}.
+\seealso{fseek, fopen}
+\done
+
+\function{fwrite}
+\synopsis{Write binary data to a file}
+\usage{UInt_Type fwrite (b, File_Type fp)}
+\description
+ The \var{fwrite} may be used to write the object represented by
+ \var{b} to an open file. If \var{b} is a string or an array, the
+ function will attempt to write all elements of the object to the
+ file. It returns the number of objects successfully written,
+ otherwise it returns \-1 upon error and sets \var{errno}
+ accordingly.
+\example
+ The following example illustrates how to write an integer array to a
+ file. In this example, \var{fp} is an open file descriptor:
+#v+
+ variable a = [1:50]; % 50 element integer array
+ if (50 != fwrite (a, fp))
+ error ("fwrite failed");
+#v-
+ Here is how to write the array one element at a time:
+#v+
+ variable a = [1:50];
+ foreach (a)
+ {
+ variable ai = ();
+ if (1 != fwrite(ai, fp))
+ error ("fwrite failed");
+ }
+#v-
+\notes
+ Not all data types may support the \var{fwrite} operation. However,
+ it is supported by all vector, scalar, and string objects.
+\seealso{fread, fputs, fopen, pack, unpack}
+\done
+
+\function{pclose}
+\synopsis{Close an object opened with popen}
+\usage{Integer_Type pclose (File_Type fp)}
+\description
+ The \var{pclose} function waits for the process associated with
+ \var{fp} to exit and the returns the exit status of the command.
+\seealso{pclose, fclose}
+\done
+
+\function{popen}
+\synopsis{Open a process}
+\usage{File_Type popen (String_Type cmd, String_Type mode)}
+\description
+ The \var{popen} function executes a process specified by \var{cmd}
+ and opens a unidirectional pipe to the newly created process. The
+ \var{mode} indicates whether or not the pipe is open for reading
+ or writing. Specifically, if \var{mode} is \exmp{"r"}, then the
+ pipe is opened for reading, or if \var{mode} is \exmp{"w"}, then the
+ pipe will be open for writing.
+
+ Upon success, a \var{File_Type} pointer will be returned, otherwise
+ the function failed and \var{NULL} will be returned.
+\notes
+ This function is not available on all systems.
+\seealso{pclose, fopen}
+\done
+
+\function{printf}
+\synopsis{Create and write a formatted string to stdout}
+\usage{Int_Type printf (String_Type fmt, ...)}
+\description
+ \var{fprintf} formats the objects specified by the variable argument
+ list according to the format \var{fmt} and write the result to
+ \var{stdout}. This function is equivalent to \var{fprintf} used
+ with the \var{stdout} file pointer. See \var{fprintf} for more
+ information.
+
+ \var{printf} returns the number of characters written to the file,
+ or \-1 upon error.
+\notes
+ Many C programmers do not check the return status of the
+ \var{printf} C library function. Make sure that if you do not care
+ about whether or not the function succeeds, then code it as in the
+ following example:
+#v+
+ () = printf ("%s laid %d eggs\n", chicken_name, num_egg);
+#v-
+\seealso{fputs, printf, fwrite, message}
+\done
+
diff --git a/libslang/doc/tm/rtl/strops.tm b/libslang/doc/tm/rtl/strops.tm
new file mode 100644
index 0000000..5b1d8b4
--- /dev/null
+++ b/libslang/doc/tm/rtl/strops.tm
@@ -0,0 +1,736 @@
+\function{Sprintf}
+\synopsis{Format objects into a string}
+\usage{String_Type Sprintf (String_Type format, ..., Integer_Type n)}
+\description
+ \var{Sprintf} formats a string from \var{n} objects according to
+ \var{format}. Unlike \var{sprintf}, the \var{Sprintf} function
+ requires the number of items to format.
+
+ The format string is a C library \var{sprintf} style format
+ descriptor. Briefly, the format string may consist of ordinary
+ characters (not including the \exmp{%} character), which are copied
+ into the output string as-is, and a conversion specification
+ introduced by the \exmp{%} character. The \var{%} character must be
+ followed by at least one other character to specify the conversion:
+#v+
+ s value is a string
+ f value is a floating point number
+ e print float in exponential form, e.g., 2.345e08
+ g print float as e or g, depending upon its value
+ c value is an ascii character
+ % print the percent character
+ d print a signed decimal integer
+ u print an unsigned decimal integer
+ o print an integer as octal
+ X print an integer as hexadecimal
+ S convert value to a string and format as string
+#v-
+ Note that \var{%S} is a \slang extension which will cause the value
+ to be formatted as string. In fact, \exmp{sprintf("%S",x)} is
+ equivalent to \exmp{sprintf("%s",string(x))}.
+#v+
+ s = Sprintf("%f is greater than %f but %s is better than %s\n",
+ PI, E, "Cake" "Pie", 4);
+#v-
+ The final argument to \var{Sprintf} is the number of items to format; in
+ this case, there are 4 items.
+\seealso{sprintf, string, sscanf}
+\done
+
+\function{create_delimited_string}
+\synopsis{Concatenate strings using a delimiter}
+\usage{String_Type create_delimited_string (delim, s_1, s_2, ..., s_n, n)}
+#v+
+ String_Type delim, s_1, ..., s_n
+ Integer_Type n
+#v-
+\description
+ \var{create_delimited_string} performs a concatenation operation on
+ the \var{n} strings \var{s_1}, ...,\var{s_n}, using the string
+ \var{delim} as a delimiter. The resulting string is equivalent to
+ one obtained via
+#v+
+ s_1 + delim + s_2 + delim + ... + s_n
+#v-
+\example
+ One use for this function is to construct path names, e.g.,
+#v+
+ create_delimited_string ("/", "user", "local", "bin", 3);
+#v-
+ will produce \exmp{"usr/local/bin"}.
+\notes
+ The expression \exmp{strcat(a,b)} is equivalent to
+ \exmp{create_delimited_string("", a, b, 2)}.
+\seealso{strjoin, is_list_element, extract_element, strchop, strcat}
+\done
+
+\function{extract_element}
+\synopsis{Extract the nth element of a string with delimiters}
+\usage{String_Type extract_element (String_Type list, Integer_Type nth, Integer_Type delim);}
+\description
+ The \var{extract_element} function may be used to extract the
+ \var{nth} element of the \var{delim} delimited list of strings
+ \var{list}. The function will return the \var{nth} element of the
+ list, unless \var{nth} specifies more elements than the list
+ contains, in which case \var{NULL} will be returned.
+ Elements in the list are numbered from \var{0}.
+\example
+ The expression
+#v+
+ extract_element ("element 0, element 1, element 2", 1, ',')
+#v-
+ returns the string \exmp{" element 1"}, whereas
+#v+
+ extract_element ("element 0, element 1, element 2", 1, ' ')
+#v-
+ returns \exmp{"0,"}.
+
+ The following function may be used to compute the number of elements
+ in the list:
+#v+
+ define num_elements (list, delim)
+ {
+ variable nth = 0;
+ while (NULL != extract_element (list, nth, delim))
+ nth++;
+ return nth;
+ }
+#v-
+
+ Alternatively, the \var{strchop} function may be more useful. In
+ fact, \var{extract_element} may be expressed in terms of the
+ function \var{strchop} as
+#v+
+ define extract_element (list, nth, delim)
+ {
+ list = strchop(list, delim, 0);
+ if (nth >= length (list))
+ return NULL;
+ else
+ return list[nth];
+ }
+#v-
+ and the \var{num_elements} function used above may be recoded more
+ simply as:
+#v+
+ define num_elements (list, delim)
+ {
+ return length (strchop (length, delim, 0));
+ }
+#v-
+\seealso{is_list_element, is_substr, strtok, strchop, create_delimited_string}
+\done
+
+\function{is_list_element}
+\synopsis{Test whether a delimited string contains a specific element}
+\usage{Integer_Type is_list_element (String_Type list, String_Type elem, Integer_Type delim)}
+\description
+ The \var{is_list_element} function may be used to determine whether
+ or not a delimited list of strings, \var{list}, contains the element
+ \var{elem}. If \var{elem} is not an element of \var{list}, the function
+ will return zero, otherwise, it returns 1 plus the matching element
+ number.
+\example
+ The expression
+#v+
+ is_list_element ("element 0, element 1, element 2", "0,", ' ');
+#v-
+ returns \exmp{2} since \exmp{"0,"} is element number one of the list
+ (numbered from zero).
+\seealso{extract_element, is_substr, create_delimited_string}
+\done
+
+\function{is_substr}
+\synopsis{Test for a specified substring within a string.}
+\usage{Integer_Type is_substr (String_Type a, String_Type b)}
+\description
+ This function may be used to determine if \var{a} contains the
+ string \var{b}. If it does not, the function returns 0; otherwise it
+ returns the position of the first occurance of \var{b} in \var{a}.
+\notes
+ It is important to remember that the first character of a string
+ corresponds to a position value of \exmp{1}.
+\seealso{substr, string_match, strreplace}
+\done
+
+\function{make_printable_string}
+\synopsis{Format a string suitable for parsing}
+\usage{String_Type make_printable_string(String_Type str)}
+\description
+ This function formats a string in such a way that it may be used as
+ an argument to the \var{eval} function. The resulting string is
+ identical to \var{str} except that it is enclosed in double quotes and the
+ backslash, newline, and double quote characters are expanded.
+\seealso{eval, str_quote_string}
+\done
+
+\function{sprintf}
+\synopsis{Format objects into a string}
+\usage{String sprintf (String format, ...);}
+\description
+ This function performs a similar task as the C function with the same
+ name. It differs from the \slang function \var{Sprintf} in that it
+ does not require the number of items to format.
+ See the documentation for \var{Sprintf} for more information.
+\seealso{Sprintf, string, sscanf, vmessage}
+\done
+
+\function{sscanf}
+\synopsis{Parse a formatted string}
+\usage{Int_Type sscanf (s, fmt, r1, ... rN)}
+#v+
+ String_Type s, fmt;
+ Ref_Type r1, ..., rN
+#v-
+\description
+ The \var{sscanf} function parses the string \var{s} according to the
+ format \var{fmt} and sets the variables whose references are given by
+ \var{r1}, ..., \var{rN}. The function returns the number of
+ references assigned, or \var{-1} upon error.
+
+ The format string \var{fmt} consists of ordinary characters and
+ conversion specifiers. A conversion specifier begins with the
+ special character \var{%} and is described more fully below. A white
+ space character in the format string matches any amount of whitespace
+ in the input string. Parsing of the format string stops whenever a
+ match fails.
+
+ The \var{%} is used to denote a conversion specifier whose general
+ form is given by \exmp{%[*][width][type]format} where the brackets
+ indicate optional items. If \var{*} is present, then the conversion
+ will be performed by no assignment to a reference will be made. The
+ \var{width} specifier specifies the maximum field width to use for
+ the conversion. The \var{type} modifier is used to indicate size of
+ the object, e.g., a short integer, as follows.
+
+ If \em{type} is given as the character \var{h}, then if the format
+ conversion is for an integer (\var{dioux}), the object assigned will
+ be a short integer. If \em{type} is \var{l}, then the conversion
+ will be to a long integer for integer conversions, or to a double
+ precession floating point number for floating point conversions.
+
+ The format specifier is a character that specifies the conversion:
+#v+
+ % Matches a literal percent character. No assigment is
+ performed.
+ d Matches a signed decimal integer.
+ D Matches a long decimal integer (equiv to `ld')
+ u Matches an unsigned decimal integer
+ U Matches an unsigned long decimal integer (equiv to `lu')
+ i Matches either a hexidecimal integer, decimal integer, or
+ octal integer.
+ I Equivalent to `li'.
+ x Matches a hexidecimal integer.
+ X Matches a long hexidecimal integer (same as `lx').
+ e,f,g Matches a decimal floating point number (Float_Type).
+ E,F,G Matches a double precision floating point number, same as `lf'.
+ s Matches a string of non-whitespace characters (String_Type).
+ c Matches one character. If width is given, width
+ characters are matched.
+ n Assigns the number of characters scanned so far.
+ [...] Matches zero or more characters from the set of characters
+ enclosed by the square brackets. If '^' is given as the
+ first character, then the complement set is matched.
+#v-
+\example
+ Suppose that \var{s} is \exmp{"Coffee: (3,4,12.4)"}. Then
+#v+
+ n = sscanf (s, "%[a-zA-Z]: (%d,%d,%lf)", &item, &x, &y, &z);
+#v-
+ will set \var{n} to \4, \var{item} to \exmp{"Coffee"}, \var{x} to \3,
+ \var{y} to \4, and \var{z} to the double precision number
+ \exmp{12.4}. However,
+#v+
+ n = sscanf (s, "%s: (%d,%d,%lf)", &item, &x, &y, &z);
+#v-
+ will set \var{n} to \1, \var{item} to \exmp{"Coffee:"} and the
+ remaining variables will not be assigned.
+\seealso{sprintf, unpack, string, atof, int, integer, string_match}
+\done
+
+\function{str_delete_chars}
+\synopsis{Delete characters from a string}
+\usage{String_Type str_delete_chars (String_Type str, String_Type del_set}
+\description
+ This function may be used to delete the set of characters specified
+ by \var{del_set} from the string \var{str}. The result is returned.
+\example
+#v+
+ str = str_delete_chars (str, "^A-Za-z");
+#v-
+ will remove all characters except \exmp{A-Z} and \exmp{a-z} from
+ \var{str}.
+\done
+
+\function{str_quote_string}
+\synopsis{Escape characters in a string.}
+\usage{String_Type str_quote_string(String_Type str, String_Type qlis, Integer_Type quote)}
+\description
+ The \var{str_quote_string} returns a string identical to \var{str}
+ except that all characters in the set specified by the string
+ \var{qlis} are escaped with the \var{quote} character, including the
+ quote character itself. This function is useful for making a
+ string that can be used in a regular expression.
+\example
+ Execution of the statements
+#v+
+ node = "Is it [the coat] really worth $100?";
+ tag = str_quote_string (node, "\\^$[]*.+?", '\\');
+#v-
+ will result in \var{tag} having the value:
+#v+
+ Is it \[the coat\] really worth \$100\?
+#v-
+\seealso{str_uncomment_string, make_printable_string}
+\done
+
+\function{str_replace}
+\synopsis{Replace a substring of a string}
+\usage{Integer_Type str_replace (String_Type a, String_Type b, String_Type c)}
+\description
+ The \var{str_replace} function replaces the first occurance of \var{b} in
+ \var{a} with \var{c} and returns an integer that indicates whether a
+ replacement was made or not. If \var{b} does not occur in \var{a}, zero is
+ returned. However, if \var{b} occurs in \var{a}, a non-zero integer is
+ returned as well as the new string resulting from the replacement.
+\notes
+ This function has been superceded by \var{strreplace}.
+\seealso{strreplace}
+\done
+
+\function{str_uncomment_string}
+\synopsis{Remove comments from a string}
+\usage{String_Type str_uncomment_string(String_Type s, String_Type beg, String_Type end)}
+\description
+ This function may be used to remove comments from a string \var{s}.
+ The parameters, \var{beg} and \var{end}, are strings of equal length
+ whose corresponding characters specify the begin and end comment
+ characters, respectively. It returns the uncommented string.
+\example
+ The expression
+#v+
+ str_uncomment_string ("Hello (testing) 'example' World", "'(", "')")
+#v-
+ returns the string \exmp{"Hello World"}.
+\notes
+ This routine does not handle multicharacter comment delimiters and it
+ assumes that comments are not nested.
+\seealso{str_quote_string}
+\done
+
+\function{strcat}
+\synopsis{Concatenate strings}
+\usage{String_Type strcat (String_Type a_1, ..., String_Type a_N)}
+\description
+ The \var{strcat} function concatenates its N \var{String_Type}
+ arguments \var{a_1}, ... \var{a_N} together and returns the result.
+\example
+#v+
+ strcat ("Hello", " ", "World");
+#v-
+ produces the string \exmp{"Hello World"}.
+\notes
+ This function is equivalent to the binary operation \exmp{a_1+...+a_N}.
+ However, \var{strcat} is much faster making it the preferred method
+ to concatenate string.
+\seealso{sprintf, create_delimited_string}
+\done
+
+\function{strchop}
+\synopsis{Chop or split a string into substrings.}
+\usage{String_Type[] strchop (String_Type str, Integer_Type delim, Integer_Type quote)}
+\description
+ The \var{strchop} function may be used to split-up a string
+ \var{str} that consists of substrings delimited by the character
+ specified by \var{delim}. If the integer \var{quote} is non-zero,
+ it will be taken as a quote character for the delimiter. The
+ function returns the substrings as an array.
+\example
+ The following function illustrates how to sort a comma separated
+ list of strings:
+#v+
+ define sort_string_list (a)
+ {
+ variable i, b, c;
+ b = strchop (a, ',', 0);
+
+ i = array_sort (b, &strcmp);
+ b = b[i]; % rearrange
+
+ % Convert array back into comma separated form
+ return strjoin (b, ",");
+ }
+#v-
+\notes
+ The semantics of this \var{strchop} and \var{strchopr} have been
+ changed since version 1.2.x of the interpreter. Old versions of
+ these functions returned the values on the stack, which meant that
+ one could not chop up arbitrarily long strings that consist of
+ many substrings.
+
+ The function \var{strchopr} should be used if it is desired to have
+ the string chopped-up in the reverse order.
+\seealso{strchopr, extract_element, strjoin, strtok}
+\done
+
+\function{strchopr}
+\synopsis{Chop or split a string into substrings.}
+\usage{String_Type[] strchopr (String_Type str, String_Type delim, String_Type quote)}
+\description
+ This routine performs exactly the same function as \var{strchop} except
+ that it returns the substrings in the reverse order. See the
+ documentation for \var{strchop} for more information.
+\seealso{strchop, extract_element, strtok, strjoin}
+\done
+
+\function{strcmp}
+\synopsis{Compare two strings}
+\usage{Interpret strcmp (String_Type a, String_Type b)}
+\description
+ The \var{strcmp} function may be used to perform a case-sensitive
+ string comparison, in the lexicongraphic sense, on strings \var{a} and
+ \var{b}. It returns 0 if the strings are identical, a negative integer
+ if \var{a} is less than \var{b}, or a positive integer if \var{a} is greater
+ than \var{b}.
+\example
+ The \var{strup} function may be used to perform a case-insensitive
+ string comparison:
+#v+
+ define case_insensitive_strcmp (a, b)
+ {
+ return strcmp (strup(a), strup(b));
+ }
+#v-
+\notes
+ One may also use one of the binary comparison operators, e.g.,
+ \exmp{a > b}.
+\seealso{strup, strncmp}
+\done
+
+\function{strcompress}
+\synopsis{Remove excess whitespace characters from a string}
+\usage{String_Type strcompress (String_Type s, String_Type white)}
+\description
+ The \var{strcompress} function compresses the string \var{s} by
+ replacing a sequence of one or more characters from the set
+ \var{white} by the first character of \var{white}. In addition, it
+ also removes all leading and trailing characters from \var{s} that
+ are part of \var{white}.
+\example
+ The expression
+#v+
+ strcompress (",;apple,,cherry;,banana", ",;");
+#v-
+ returns the string \exmp{"apple,cherry,banana"}.
+\seealso{strtrim, strtrans}
+\done
+
+\function{string_match}
+\synopsis{Match a string against a regular expression}
+\usage{Integer_Type string_match(String_Type str, String_Type pat, Integer_Type pos)}
+\description
+ The \var{string_match} function returns zero if \var{str} does not
+ match regular expression specified by \var{pat}. This function
+ performs the match starting at position \var{pos} (numbered from 1) in
+ \var{str}. This function returns the position of the start of the
+ match. To find the exact substring actually matched, use
+ \var{string_match_nth}.
+\seealso{string_match_nth, strcmp, strncmp}
+\done
+
+\function{string_match_nth}
+\synopsis{Get the result of the last call to string_match}
+\usage{(Integer_Type, Integer_Type) = string_match_nth(Integer_Type nth)}
+\description
+ The \var{string_match_nth} function returns two integers describing
+ the result of the last call to \var{string_match}. It returns both
+ the offset into the string and the length of characters matches by
+ the \var{nth} submatch.
+
+ By convention, \var{nth} equal to zero means the entire match.
+ Otherwise, \var{nth} must be an integer with a value 1 through 9,
+ and refers to the set of characters matched by the \var{nth} regular
+ expression enclosed by the pairs \exmp{\\(, \\)}.
+\example
+ Consider:
+#v+
+ variable matched, pos, len;
+ matched = string_match("hello world", "\\([a-z]+\\) \\([a-z]+\\)", 1);
+ if (matched) (pos, len) = string_match_nth(2);
+#v-
+ This will set \var{matched} to 1 since a match will be found at the
+ first position, \var{pos} to 6 since \var{w} is offset 6 characters
+ from the beginning of the string, and \var{len} to 5 since
+ \exmp{"world"} is 5 characters long.
+\notes
+ The position offset is \em{not} affected by the value of the offset
+ parameter to the \var{string_match} function. For example, if the
+ value of the last parameter to the \var{string_match} function had
+ been 3, \var{pos} would still have been set to 6.
+
+ Note also that \var{string_match_nth} returns the \em{offset} from
+ the beginning of the string and not the position of the match.
+\seealso{string_match}
+\done
+
+\function{strjoin}
+\synopsis{Concatenate elements of a string array}
+\usage{String_Type strjoin (Array_Type a, String_Type delim)}
+\description
+ The \var{strjoin} function operates on an array of strings by joining
+ successive elements together separated with a delimiter \var{delim}.
+ If \var{delim} is the empty string \exmp{""}, then the result will
+ simply be the concatenation of the elements.
+\example
+ Suppose that
+#v+
+ days = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
+#v-
+ Then \exmp{strjoin (days,"+")} will produce
+ \exmp{"Sun+Mon+Tue+Wed+Thu+Fri+Sat+Sun"}. Similarly,
+ \exmp{strjoin (["","",""], "X")} will produce \exmp{"XX"}.
+\seealso{create_delimited_string, strchop, strcat}
+\done
+
+\function{strlen}
+\synopsis{Compute the length of a string}
+\usage{Integer_Type strlen (String_Type a)}
+\description
+ The \var{strlen} function may be used to compute the length of a string.
+\example
+ After execution of
+#v+
+ variable len = strlen ("hello");
+#v-
+ \var{len} will have a value of \exmp{5}.
+\seealso{bstrlen, length, substr}
+\done
+
+\function{strlow}
+\synopsis{Convert a string to lowercase}
+\usage{String_Type strlow (String_Type s)}
+\description
+ The \var{strlow} function takes a string \var{s} and returns another
+ string identical to \var{s} except that all upper case characters
+ that comprise \var{s} will be converted to lower case.
+\example
+ The function
+#v+
+ define Strcmp (a, b)
+ {
+ return strcmp (strlow (a), strlow (b));
+ }
+#v-
+ performs a case-insensitive comparison operation of two strings by
+ converting them to lower case first.
+\seealso{strup, tolower, strcmp, strtrim, define_case}
+\done
+
+\function{strncmp}
+\synopsis{Compare the first few characters of two strings}
+\usage{Integer_Type strncmp (String_Type a, String_Type b, Integer_Type n)}
+\description
+ This function behaves like \var{strcmp} except that it compares only the
+ first \var{n} characters in the strings \var{a} and \var{b}. See
+ the documentation for \var{strcmp} for information about the return
+ value.
+\example
+ The expression
+#v+
+ strcmp ("apple", "appliance", 3);
+#v-
+ will return zero since the first three characters match.
+\seealso{strcmp, strlen}
+\done
+
+\function{strreplace}
+\synopsis{Replace one or more substrings}
+\usage{(new, n) = strreplace (a, b, c, max_n)}
+#v+
+ String_Type a, b, c, rep;
+ Int_Type n, max_n;
+#v-
+\description
+ The \var{strreplace} function may be used to replace one or more
+ occurances of \var{b} in \var{a} with \var{c}. If the integer
+ \var{max_n} is positive, then the first \var{max_n} occurances of
+ \var{b} in \var{a} will be replaced. Otherwise, if \var{max_n} is
+ negative, then the last \exmp{abs(max_n)} occurances will be replaced.
+
+ The function returns the resulting string and an integer indicating
+ how many replacements were made.
+\example
+ The following function illustrates how \var{strreplace} may be used
+ to remove all occurances of a specified substring
+#v+
+ define delete_substrings (a, b)
+ {
+ (a, ) = strreplace (a, b, "", strlen (a));
+ return a;
+ }
+#v-
+\seealso{is_substr, strsub, strtrim, strtrans, str_delete_chars}
+\done
+
+\function{strsub}
+\synopsis{Replace a character with another in a string.}
+\usage{String_Type strsub (String_Type s, Integer_Type pos, Integer_Type ch)}
+\description
+ The \var{strsub} character may be used to substitute the character
+ \var{ch} for the character at position \var{pos} of the string
+ \var{s}. The resulting string is returned.
+\example
+#v+
+ define replace_spaces_with_comma (s)
+ {
+ variable n;
+ while (n = is_substr (s, " "), n) s = strsub (s, n, ',');
+ return s;
+ }
+#v-
+ For uses such as this, the \var{strtrans} function is a better choice.
+\notes
+ The first character in the string \var{s} is specified by \var{pos}
+ equal to 1.
+\seealso{is_substr, strreplace, strlen}
+\done
+
+\function{strtok}
+\synopsis{Extract tokens from a string}
+\usage{String_Type[] strtok (String_Type str [,String_Type white])}
+\description
+ \var{strtok} breaks the string \var{str} into a series of tokens and
+ returns them as an array of strings. If the second parameter
+ \var{white} is present, then it specifies the set of characters that
+ are to be regarded as whitespace when extracting the tokens, and may
+ consist of the whitespace characters or a range of such characters.
+ If the first character of \var{white} is \exmp{'^'}, then the
+ whitespace characters consist of all characters except those in
+ \var{white}. For example, if \var{white} is \exmp{" \\t\\n,;."},
+ then those characters specifiy the whitespace characters. However,
+ if \var{white} is given by \exmp{"^a-zA-Z0-9_"}, then any character
+ is a whitespace character except those in the ranges \exmp{a-z},
+ \exmp{A-Z}, \exmp{0-9}, and the underscore character.
+
+ If the second parameter is not present, then it defaults to
+ \exmp{" \\t\\r\\n\\f"}.
+\example
+ The following example may be used to count the words in a text file:
+#v+
+ define count_words (file)
+ {
+ variable fp, line, count;
+
+ fp = fopen (file, "r");
+ if (fp == NULL) return -1;
+
+ count = 0;
+ while (-1 != fgets (&line, fp))
+ {
+ line = strtok (line, "^a-zA-Z");
+ count += length (line);
+ }
+ () = fclose (fp);
+ return count;
+ }
+#v-
+\seealso{strchop, strcompress, extract_element, strjoin}
+\done
+
+\function{strtrans}
+\synopsis{Replace characters in a string}
+\usage{String_Type strtrans (str, old_set, new_set)}
+#v+
+ String_Type str, old_set, new_set;
+#v-
+\description
+ The \var{strtrans} function may be used to replace all the characters
+ from the set \var{old_set} with the corresponding characters from
+ \var{new_set} in the string \var{str}. If \var{new_set} is empty,
+ then the characters in \var{old_set} will be removed from \var{str}.
+ This function returns the result.
+\example
+#v+
+ str = strtrans (str, "A-Z", "a-z"); % lower-case str
+ str = strtrans (str, "^0-9", " "); % Replace anything but 0-9 by space
+#v-
+\seealso{strreplace, strtrim, strup, strlow}
+\done
+
+\function{strtrim}
+\synopsis{Remove whitespace from the ends of a string}
+\usage{String_Type strtrim (String_Type s [,String_Type w])}
+\description
+ The \var{strtrim} function removes all leading and trailing whitespace
+ characters from the string \var{s} and returns the result. The
+ optional second parameter specifies the set of whitespace
+ characters. If the argument is not present, then the set defaults
+ to \exmp{" \\t\\r\\n"}.
+\seealso{strtrim_beg, strtrim_end, strcompress}
+\done
+
+\function{strtrim_beg}
+\synopsis{Remove leading whitespace from a string}
+\usage{String_Type strtrim_beg (String_Type s [,String_Type w])}
+\description
+ The \var{strtrim_beg} function removes all leading whitespace
+ characters from the string \var{s} and returns the result. The
+ optional second parameter specifies the set of whitespace
+ characters. If the argument is not present, then the set defaults
+ to \exmp{" \\t\\r\\n"}.
+\seealso{strtrim, strtrim_end, strcompress}
+\done
+
+\function{strtrim_end}
+\synopsis{Remove trailing whitespace from a string}
+\usage{String_Type strtrim_end (String_Type s [,String_Type w])}
+\description
+ The \var{strtrim_end} function removes all trailing whitespace
+ characters from the string \var{s} and returns the result. The
+ optional second parameter specifies the set of whitespace
+ characters. If the argument is not present, then the set defaults
+ to \exmp{" \\t\\r\\n"}.
+\seealso{strtrim, strtrim_beg, strcompress}
+\done
+
+\function{strup}
+\synopsis{Convert a string to uppercase}
+\usage{String_Type strup (String_Type s)}
+\description
+ The \var{strup} function takes a string \var{s} and returns another
+ string identical to \var{s} except that all lower case characters
+ that comprise \var{s} will be converted to upper case.
+\example
+ The function
+#v+
+ define Strcmp (a, b)
+ {
+ return strcmp (strup (a), strup (b));
+ }
+#v-
+ performs a case-insensitive comparison operation of two strings by
+ converting them to upper case first.
+\seealso{strlow, toupper, strcmp, strtrim, define_case, strtrans}
+\done
+
+\function{substr}
+\synopsis{Extract a substring from a string}
+\usage{String_Type substr (String_Type s, Integer_Type n, Integer_Type len)}
+\description
+ The \var{substr} function returns a substring with length \var{len}
+ of the string \var{s} beginning at position \var{n}. If \var{len} is
+ \exmp{-1}, the entire length of the string \var{s} will be used for
+ \var{len}. The first character of \var{s} is given by \var{n} equal
+ to 1.
+\example
+#v+
+ substr ("To be or not to be", 7, 5);
+#v-
+ returns \exmp{"or no"}
+\notes
+ In many cases it is more convenient to use array indexing rather
+ than the \var{substr} function. In fact, \exmp{substr(s,i+1,strlen(s))} is
+ equivalent to \exmp{s[[i:]]}.
+\seealso{is_substr, strlen}
+\done
+
diff --git a/libslang/doc/tm/rtl/struct.tm b/libslang/doc/tm/rtl/struct.tm
new file mode 100644
index 0000000..9d23263
--- /dev/null
+++ b/libslang/doc/tm/rtl/struct.tm
@@ -0,0 +1,104 @@
+\function{_push_struct_field_values}
+\synopsis{Push the values of a structure's fields onto the stack}
+\usage{Integer_Type num = _push_struct_field_values (Struct_Type s)}
+\description
+ The \var{_push_struct_field_values} function pushes the values of
+ all the fields of a structure onto the stack, returning the
+ number of items pushed. The fields are pushed such that the last
+ field of the structure is pushed first.
+\seealso{get_struct_field_names, get_struct_field}
+\done
+
+\function{get_struct_field}
+\synopsis{Get the value associated with a structure field}
+\usage{x = get_struct_field (Struct_Type s, String field_name)}
+\description
+ The \var{get_struct_field} function gets the value of the field
+ whose name is specified by \var{field_name} of the structure \var{s}.
+\example
+ The following example illustrates how this function may be used to
+ to print the value of a structure.
+#v+
+ define print_struct (s)
+ {
+ variable name;
+
+ foreach (get_struct_field_names (s))
+ {
+ name = ();
+ value = get_struct_field (s, name);
+ vmessage ("s.%s = %s\n", name, string(value));
+ }
+ }
+#v-
+\seealso{set_struct_field, get_struct_field_names, array_info}
+
+\done
+
+\function{get_struct_field_names}
+\synopsis{Retrieve the field names associated with a structure}
+\usage{String_Type[] = get_struct_field_names (Struct_Type s)}
+\description
+ The \var{get_struct_field_names} function returns an array of
+ strings whose elements specify the names of the fields of the
+ struct \var{s}.
+\example
+ The following example illustrates how the
+ \var{get_struct_field_names} function may be used to print the
+ value of a structure.
+#v+
+ define print_struct (s)
+ {
+ variable name, value;
+
+ foreach (get_struct_field_names (s))
+ {
+ name = ();
+ value = get_struct_field (s, name);
+ vmessage ("s.%s = %s\n", name, string (value));
+ }
+ }
+#v-
+\seealso{_push_struct_field_values, get_struct_field}
+\done
+
+\function{is_struct_type}
+\synopsis{Determine whether or not an object is a structure}
+\usage{Integer_Type is_struct_type (X)}
+\description
+ The \var{is_struct_type} function returns \1 if the parameter
+ refers to a structure or a user-defined type. If the object is
+ neither, \0 will be returned.
+\seealso{typeof, _typeof}
+\done
+
+\function{set_struct_field}
+\synopsis{Set the value associated with a structure field}
+\usage{set_struct_field (s, field_name, field_value)}
+#v+
+ Struct_Type s;
+ String_Type field_name;
+ Generic_Type field_value;
+#v-
+\description
+ The \var{set_struct_field} function sets the value of the field
+ whose name is specified by \var{field_name} of the structure
+ \var{s} to \var{field_value}.
+\seealso{get_struct_field, get_struct_field_names, set_struct_fields, array_info}
+\done
+
+\function{set_struct_fields}
+\synopsis{Set the fields of a structure}
+\usage{set_struct_fields (Struct_Type s, ...)}
+\description
+ The \var{set_struct_fields} function may be used to set zero or more
+ fields of a structure. The fields are set in the order in which
+ they were created when the structure was defined.
+\example
+#v+
+ variable s = struct { name, age, height };
+ set_struct_fields (s, "Bill", 13, 64);
+#v-
+\seealso{set_struct_field, get_struct_field_names}
+\done
+
diff --git a/libslang/doc/tm/rtl/time.tm b/libslang/doc/tm/rtl/time.tm
new file mode 100644
index 0000000..bc11de4
--- /dev/null
+++ b/libslang/doc/tm/rtl/time.tm
@@ -0,0 +1,137 @@
+\function{_time}
+\synopsis{Get the current time in seconds}
+\usage{ULong_Type _time ()}
+\description
+ The \var{_time} function returns the number of elapsed seconds since
+ 00:00:00 GMT, January 1, 1970. The \var{ctime} function may be used
+ to convert this into a string representation.
+\seealso{ctime, time, localtime, gmtime}
+\done
+
+\function{ctime}
+\synopsis{Convert a calendar time to a string}
+\usage{String_Type ctime(ULong_Type secs)}
+\description
+ This function returns a string representation of the time as given
+ by \var{secs} seconds since 1970.
+\seealso{time, _time, localtime, gmtime}
+\done
+
+\function{gmtime}
+\synopsis{Break down a time in seconds to GMT timezone}
+\usage{Struct_Type gmtime (Long_Type secs)}
+\description
+ The \var{gmtime} function is exactly like \var{localtime} except
+ that the values in the structure it returns are with respect to GMT
+ instead of the local timezone. See the documentation for
+ \var{localtime} for more information.
+\notes
+ On systems that do not support the \var{gmtime} C library function,
+ this function is the same as \var{localtime}.
+\seealso{localtime, _time}
+\done
+
+\function{localtime}
+\synopsis{Break down a time in seconds to local timezone}
+\usage{Struct_Type localtime (Long_Type secs)}
+\description
+ The \var{localtime} function takes a parameter \var{secs}
+ representing the number of seconds since 00:00:00, January 1 1970
+ UTC and returns a structure containing information about \var{secs}
+ in the local timezone. The structure contains the following
+ \var{Int_Type} fields:
+
+ \var{tm_sec} The number of seconds after the minute, normally
+ in the range 0 to 59, but can be up to 61 to allow for
+ leap seconds.
+
+ \var{tm_min} The number of minutes after the hour, in the
+ range 0 to 59.
+
+ \var{tm_hour} The number of hours past midnight, in the range
+ 0 to 23.
+
+ \var{tm_mday} The day of the month, in the range 1 to 31.
+
+ \var{tm_mon} The number of months since January, in the range
+ 0 to 11.
+
+ \var{tm_year} The number of years since 1900.
+
+ \var{tm_wday} The number of days since Sunday, in the range 0
+ to 6.
+
+ \var{tm_yday} The number of days since January 1, in the
+ range 0 to 365.
+
+ \var{tm_isdst} A flag that indicates whether daylight saving
+ time is in effect at the time described. The value is
+ positive if daylight saving time is in effect, zero if it
+ is not, and negative if the information is not available.
+\seealso{gmtime, _time, ctime}
+\done
+
+\function{tic}
+\synopsis{Start timing}
+\usage{void tic ()}
+\description
+ The \var{tic} function restarts the internal clock used for timing
+ the execution of commands. To get the elapsed time of the clock,
+ use the \var{toc} function.
+\seealso{toc, times}
+\done
+
+\function{time}
+\synopsis{Return the current data and time as a string}
+\usage{String_Type time ()}
+\description
+ This function returns the current time as a string of the form:
+#v+
+ Sun Apr 21 13:34:17 1996
+#v-
+\seealso{ctime, message, substr}
+\done
+
+\function{times}
+\synopsis{Get process times}
+\usage{Struct_Type times ()}
+\description
+ The \var{times} function returns a structure containing the
+ following fields:
+#v+
+ tms_utime (user time)
+ tms_stime (system time)
+ tms_cutime (user time of child processes)
+ tms_cstime (system time of child processes)
+#v-
+\notes
+ Not all systems support this function.
+\seealso{tic, toc, _times}
+\done
+
+\function{toc}
+\synopsis{Get elapsed CPU time}
+\usage{Double_Type toc ()}
+\description
+ The \var{toc} function returns the elapsed CPU time in seconds since
+ the last call to \var{tic}. The CPU time is the amount of time the
+ CPU spent running the code of the current process.
+\example
+ The \var{tic} and \var{toc} functions are ideal for timing the
+ execution of the interpreter:
+#v+
+ variable a = "hello", b = "world", c, n = 100000, t;
+
+ tic (); loop (n) c = a + b; t = toc ();
+ vmessage ("a+b took %f seconds\n", t);
+ tic (); loop (n) c = strcat(a,b); t = toc ();
+ vmessage ("strcat took %f seconds\n", t);
+#v-
+\notes
+ This function may not be available on all systems.
+
+ The implementation of this function is based upon the \var{times}
+ system call. The precision of the clock is system dependent.
+\seealso{tic, times, _time}
+\done
+
diff --git a/libslang/doc/tm/rtl/tm-sort.sl b/libslang/doc/tm/rtl/tm-sort.sl
new file mode 100755
index 0000000..ca73827
--- /dev/null
+++ b/libslang/doc/tm/rtl/tm-sort.sl
@@ -0,0 +1,153 @@
+#! /usr/bin/env slsh
+_debug_info = 1;
+
+if (__argc < 2)
+{
+ () = fprintf (stderr, "Usage: %s files....\n", __argv[0]);
+ exit (1);
+}
+
+static variable Data;
+
+static define init ()
+{
+ Data = Assoc_Type[String_Type];
+}
+
+static define warning ()
+{
+ variable args = __pop_args (_NARGS);
+ () = fprintf (stderr, "***WARNING: %s\n", sprintf (__push_args ()));
+}
+
+
+static define process_function (line, fp)
+{
+ variable fname;
+ variable lines;
+
+ fname = strtrim (strtok (line, "{}")[1]);
+
+ lines = line;
+#iftrue
+ foreach (fp)
+ {
+ line = ();
+ lines = strcat (lines, line);
+ if (0 == strncmp ("\\done", line, 5))
+ break;
+ }
+#else
+ while (-1 != fgets (&line, fp))
+ {
+ lines += line;
+ if (0 == strncmp ("\\done", line, 5))
+ break;
+ }
+#endif
+ if (assoc_key_exists (Data, fname))
+ {
+ warning ("Key %s already exists", fname);
+ return -1;
+ }
+
+ Data[fname] = lines;
+ return 0;
+}
+
+static define process_variable (line, fp)
+{
+ % warning ("process_variable not implemented");
+ process_function (line, fp);
+}
+
+static define read_file_contents (file)
+{
+ variable fp = fopen (file, "r");
+ variable n = 0;
+ variable line;
+
+ if (fp == NULL)
+ {
+ () = fprintf (stderr, "Unable to open %s\n", file);
+ return -1;
+ }
+
+
+ %while (-1 != fgets (&line, fp))
+ foreach (fp)
+ {
+ line = ();
+ if (0 == strncmp (line, "\\function{", 10))
+ {
+ if (-1 == process_function (line, fp))
+ return -1;
+
+ continue;
+ }
+
+ if (0 == strncmp (line, "\\variable{", 10))
+ {
+ if (-1 == process_variable (line, fp))
+ return -1;
+
+ continue;
+ }
+ }
+
+ () = fclose (fp);
+ return 0;
+}
+
+static define sort_and_write_file_elements (file)
+{
+ variable fp;
+ variable i, keys;
+ variable backup_file;
+
+ backup_file = file + ".BAK";
+ () = remove (backup_file);
+ () = rename (file, backup_file);
+
+ fp = fopen (file, "w");
+ if (fp == NULL)
+ return -1;
+
+ keys = assoc_get_keys (Data);
+ i = array_sort (keys, &strcmp);
+
+ foreach (keys[i])
+ {
+ variable k = ();
+
+ () = fputs (Data[k], fp);
+ () = fputs ("\n", fp);
+ }
+
+ () = fclose (fp);
+
+ return 0;
+}
+
+
+static define process_file (file)
+{
+ init ();
+
+ () = fprintf (stdout, "Processing %s ...", file);
+ () = fflush (stdout);
+
+ if (-1 == read_file_contents (file))
+ return -1;
+
+ if (-1 == sort_and_write_file_elements (file))
+ return -1;
+
+ () = fputs ("done.\n", stdout);
+ return 0;
+}
+
+foreach (__argv[[1:]])
+ process_file ();
+
+exit (0);
diff --git a/libslang/doc/tm/rtl/type.tm b/libslang/doc/tm/rtl/type.tm
new file mode 100644
index 0000000..342f012
--- /dev/null
+++ b/libslang/doc/tm/rtl/type.tm
@@ -0,0 +1,245 @@
+\function{_slang_guess_type}
+\synopsis{Guess the data type that a string represents.}
+\usage{DataType_Type _slang_guess_type (String_Type s)}
+\description
+ This function tries to determine whether its argument \var{s}
+ represents an integer (short, int, long), floating point (float,
+ double), or a complex number. If it appears to be none of these,
+ then a string is assumed. It returns one of the following values
+ depending on the format of the string \var{s}:
+#v+
+ Short_Type : short integer (e.g., "2h")
+ UShort_Type : unsigned short integer (e.g., "2hu")
+ Integer_Type : integer (e.g., "2")
+ UInteger_Type : unsigned integer (e.g., "2")
+ Long_Type : long integer (e.g., "2l")
+ ULong_Type : unsigned long integer (e.g., "2l")
+ Float_Type : float (e.g., "2.0f")
+ Double_Type : double (e.g., "2.0")
+ Complex_Type : imaginary (e.g., "2i")
+ String_Type : Anything else. (e.g., "2foo")
+#v-
+ For example, \exmp{_slang_guess_type("1e2")} returns
+ \var{Double_Type} but \exmp{_slang_guess_type("e12")} returns
+ \var{String_Type}.
+\seealso{integer, string, double, atof}
+\done
+
+\function{_typeof}
+\synopsis{Get the data type of an object}
+\usage{DataType_Type _typeof (x)}
+\description
+ This function is similar to the \var{typeof} function except in the
+ case of arrays. If the object \exmp{x} is an array, then the data
+ type of the array will be returned. otherwise \var{_typeof} returns
+ the data type of \var{x}.
+\example
+#v+
+ if (Integer_Type == _typeof (x))
+ message ("x is an integer or an integer array");
+#v-
+\seealso{typeof, array_info, _slang_guess_type, typecast}
+\done
+
+\function{atof}
+\synopsis{Convert a string to a double precision number}
+\usage{Double_Type atof (String_Type s)}
+\description
+ This function converts a string \var{s} to a double precision value
+ and returns the result. It performs no error checking on the format
+ of the string. The function \var{_slang_guess_type} may be used to
+ check the syntax of the string.
+\example
+#v+
+ define error_checked_atof (s)
+ {
+ switch (_slang_guess_type (s))
+ {
+ case Double_Type:
+ return atof (s);
+ }
+ {
+ case Integer_Type:
+ return double (integer (s));
+ }
+
+ verror ("%s is not a double", s);
+ }
+#v-
+\seealso{typecast, double, _slang_guess_type}
+\done
+
+\function{char}
+\synopsis{Convert an ascii value into a string}
+\usage{String_Type char (Integer_Type c)}
+\description
+ The \var{char} function converts an integer ascii value \var{c} to a string
+ of unit length such that the first character of the string is \var{c}.
+ For example, \exmp{char('a')} returns the string \exmp{"a"}.
+\seealso{integer, string, typedef}
+\done
+
+\function{define_case}
+\synopsis{Define upper-lower case conversion.}
+\usage{define_case (Integer_Type ch_up, Integer_Type ch_low);}
+\description
+ This function defines an upper and lowercase relationship between two
+ characters specified by the arguments. This relationship is used by
+ routines which perform uppercase and lowercase conversions.
+ The first integer \var{ch_up} is the ascii value of the uppercase character
+ and the second parameter \var{ch_low} is the ascii value of its
+ lowercase counterpart.
+\seealso{strlow, strup}
+\done
+
+\function{double}
+\synopsis{Convert an object to double precision}
+\usage{result = double (x)}
+\description
+ The \var{double} function typecasts an object \var{x} to double
+ precision. For example, if \var{x} is an array of integers, an
+ array of double types will be returned. If an object cannot be
+ converted to \var{Double_Type}, a type-mismatch error will result.
+\notes
+ The \var{double} function is equivalent to the typecast operation
+#v+
+ typecast (x, Double_Type)
+#v-
+ To convert a string to a double precision number, use the \var{atof}
+ function.
+\seealso{typecast, atof, int}
+\done
+
+\function{int}
+\synopsis{Typecast an object to an integer}
+\usage{int (s)}
+\description
+ This function performs a typecast of \var{s} from its data type to
+ an object of \var{Integer_Type}. If \var{s} is a string, it returns
+ returns the ascii value of the first character of the string
+ \var{s}. If \var{s} is \var{Double_Type}, \var{int} truncates the
+ number to an integer and returns it.
+\example
+ \var{int} can be used to convert single character strings to
+ integers. As an example, the intrinsic function \var{isdigit} may
+ be defined as
+#v+
+ define isdigit (s)
+ {
+ if ((int (s) >= '0') and (int (s) <= '9')) return 1;
+ return 0;
+ }
+#v-
+\notes
+ This function is equalent to \exmp{typecast (s, Integer_Type)};
+\seealso{typecast, double, integer, char, isdigit}
+\done
+
+\function{integer}
+\synopsis{Convert a string to an integer}
+\usage{Integer_Type integer (String_Type s)}
+\description
+ The \var{integer} function converts a string representation of an
+ integer back to an integer. If the string does not form a valid
+ integer, a type-mismatch error will be generated.
+\example
+ \exmp{integer ("1234")} returns the integer value \exmp{1234}.
+\notes
+ This function operates only on strings and is not the same as the
+ more general \var{typecast} operator.
+\seealso{typecast, _slang_guess_type, string, sprintf, char}
+\done
+
+\function{isdigit}
+\synopsis{Tests for a decimal digit character}
+\usage{Integer_Type isdigit (String_Type s)}
+\description
+ This function returns a non-zero value if the first character in the
+ string \var{s} is a digit; otherwise, it returns zero.
+\example
+ A simple, user defined implementation of \var{isdigit} is
+#v+
+ define isdigit (s)
+ {
+ return ((s[0] <= '9') and (s[0] >= '0'));
+ }
+#v-
+ However, the intrinsic function \var{isdigit} executes many times faster
+ than the equivalent representation defined above.
+\notes
+ Unlike the C function with the same name, the \slang function takes
+ a string argument.
+\seealso{int, integer}
+\done
+
+\function{string}
+\synopsis{Convert an object to a string representation.}
+\usage{Integer_Type string (obj)}
+\description
+ The \var{string} function may be used to convert an object
+ \var{obj} of any type to a string representation.
+ For example, \exmp{string(12.34)} returns \exmp{"12.34"}.
+\example
+#v+
+ define print_anything (anything)
+ {
+ message (string (anything));
+ }
+#v-
+\notes
+ This function is \em{not} the same as typecasting to a \var{String_Type}
+ using the \var{typecast} function.
+\seealso{typecast, sprintf, integer, char}
+\done
+
+\function{tolower}
+\synopsis{Convert a character to lowercase.}
+\usage{Integer_Type lower (Integer_Type ch)}
+\description
+ This function takes an integer \var{ch} and returns its lowercase
+ equivalent.
+\seealso{toupper, strup, strlow, int, char, define_case}
+\done
+
+\function{toupper}
+\synopsis{Convert a character to uppercase.}
+\usage{Integer_Type toupper (Integer_Type ch)}
+\description
+ This function takes an integer \var{ch} and returns its uppercase
+ equivalent.
+\seealso{tolower, strup, strlow, int, char, define_case}
+\done
+
+\function{typecast}
+\synopsis{Convert an object from one data type to another.}
+\usage{typecast (x, new_type)}
+\description
+ The \var{typecast} function performs a generic typecast operation on
+ \var{x} to convert it to \var{new_type}. If \var{x} represents an
+ array, the function will attempt to convert all elements of \var{x}
+ to \var{new_type}. Not all objects can be converted and a
+ type-mismatch error will result upon failure.
+\example
+#v+
+ define to_complex (x)
+ {
+ return typecast (x, Complex_Type);
+ }
+#v-
+ defines a function that converts its argument, \var{x} to a complex
+ number.
+\seealso{int, double, typeof}
+\done
+
+\function{typeof}
+\synopsis{Get the data type of an object.}
+\usage{DataType_Type typeof (x)}
+\description
+ This function returns the data type of \var{x}.
+\example
+#v+
+ if (Integer_Type == typeof (x)) message ("x is an integer");
+#v-
+\seealso{_typeof, is_struct_type, array_info, _slang_guess_type, typecast}
+\done
+
diff --git a/libslang/doc/tm/rtl/whatelse.sl b/libslang/doc/tm/rtl/whatelse.sl
new file mode 100755
index 0000000..fec4f0d
--- /dev/null
+++ b/libslang/doc/tm/rtl/whatelse.sl
@@ -0,0 +1,116 @@
+#! /usr/bin/env slsh
+% -*- slang -*-
+
+% This file is used to determine what functions still need documenting.
+% I think that it provides a good example of the use of associative arrays.
+
+_debug_info = 1;
+
+variable Src_Files = "../../../src/*.c";
+variable TM_Files = "*.tm";
+variable Unwanted_Files = "../../../src/calc.c";
+
+define grep (pat, files)
+{
+ if (strlen (files) == 0)
+ return String_Type[0];
+
+ variable fp = popen (sprintf ("rgrep '%s' %s", pat, files), "r");
+ variable matches;
+
+ matches = fgetslines (fp);
+ () = pclose (fp);
+
+ return matches;
+}
+
+
+static define prune_array (a, b)
+{
+ foreach (b) using ("keys")
+ {
+ variable k = ();
+ assoc_delete_key (a, k);
+ }
+}
+
+define get_with_pattern (a, pat, white)
+{
+ variable f;
+
+ foreach (grep (pat, Src_Files))
+ {
+ f = ();
+
+ f = strtok (f, white)[1];
+ a [f] = 1;
+ }
+
+ if (Unwanted_Files != NULL) foreach (grep (pat, Unwanted_Files))
+ {
+ f = ();
+ f = strtok (f, white)[1];
+ assoc_delete_key (a, f);
+ }
+}
+
+define get_src_intrinsics ()
+{
+ variable f;
+ variable src = Assoc_Type[Int_Type];
+
+ get_with_pattern (src, "^[ \t]+MAKE_INTRINSIC.*(\".*\"", "\"");
+ get_with_pattern (src, "^[ \t]+MAKE_MATH_UNARY.*(\".*\"", "\"");
+ get_with_pattern (src, "^[ \t]+MAKE_VARIABLE.*(\".*\"", "\"");
+ get_with_pattern (src, "^[ \t]+MAKE_DCONSTANT.*(\".*\"", "\"");
+ get_with_pattern (src, "^[ \t]+MAKE_ICONSTANT.*(\".*\"", "\"");
+
+ return src;
+}
+
+define get_doc_intrinsics ()
+{
+ variable funs;
+ variable doc = Assoc_Type[Int_Type];
+
+ funs = grep ("^\\\\function{", TM_Files);
+ foreach (funs)
+ {
+ variable f;
+ f = ();
+ f = strtok (f, "{}")[1];
+ doc [f] = 1;
+ }
+ funs = grep ("^\\\\variable{", TM_Files);
+ foreach (funs)
+ {
+ f = ();
+ f = strtok (f, "{}")[1];
+ doc [f] = 1;
+ }
+ return doc;
+}
+
+
+define main ()
+{
+ variable k;
+ variable src, doc;
+
+ doc = get_doc_intrinsics ();
+ src = get_src_intrinsics ();
+
+ prune_array (src, doc);
+
+ k = assoc_get_keys (src);
+ k = k[array_sort(k)];
+
+ foreach (k)
+ {
+ message ();
+ }
+}
+
+main ();
+
+
diff --git a/libslang/doc/tm/slang.tm b/libslang/doc/tm/slang.tm
new file mode 100644
index 0000000..3e02e3d
--- /dev/null
+++ b/libslang/doc/tm/slang.tm
@@ -0,0 +1,4077 @@
+#% -*- mode: tm; mode: fold -*-
+
+#% text-macro definitions #%{{{
+#i linuxdoc.tm
+
+#d slang \bf{S-Lang}
+#d slrn \bf{slrn}
+#d jed \bf{jed}
+#d kw#1 \tt{$1}
+#d exmp#1 \tt{$1}
+#d var#1 \tt{$1}
+#d ldots ...
+#d times *
+#d math#1 $1
+#d sc#1 \tt{$1}
+#d verb#1 \tt{$1}
+#d sldxe \bf{sldxe}
+#d url#1 <htmlurl url="$1" name="$1">
+#d slang-library-reference \bf{The \slang Library Reference}
+#d chapter#1 <chapt>$1<p>
+#d preface <preface>
+#d tag#1 <tag>$1</tag>
+#d appendix <appendix>
+
+#d NULL <tt>NULL</tt>
+#d kbd#1 <tt>$1</tt>
+
+#d documentstyle book
+
+#%}}}
+
+\linuxdoc
+
+\begin{\documentstyle}
+
+\title A Guide to the S-Lang Language
+\author John E. Davis, \tt{davis@space.mit.edu}
+\date \__today__
+
+\toc
+
+#i preface.tm
+
+\chapter{Introduction} #%{{{
+
+ \slang is a powerful interpreted language that may be embedded into
+ an application to make the application extensible. This enables
+ the application to be used in ways not envisioned by the programmer,
+ thus providing the application with much more flexibility and
+ power. Examples of applications that take advantage of the
+ interpreter in this way include the \jed editor and the \slrn
+ newsreader.
+
+\sect{Language Features}
+
+ The language features both global and local variables, branching
+ and looping constructs, user-defined functions, structures,
+ datatypes, and arrays. In addition, there is limited support for
+ pointer types. The concise array syntax rivals that of commercial
+ array-based numerical computing environments.
+
+\sect{Data Types and Operators} #%{{{
+
+ The language provides built-in support for string, integer (signed
+ and unsigned long and short), double precision floating point, and
+ double precision complex numbers. In addition, it supports user
+ defined structure types, multi-dimensional array types, and
+ associative arrays. To facilitate the construction of
+ sophisticated data structures such as linked lists and trees, a
+ `reference' type was added to the language. The reference type
+ provides much of the same flexibility as pointers in other
+ languages. Finally, applications embedding the interpreter may
+ also provide special application specific types, such as the
+ \var{Mark_Type} that the \jed editor provides.
+
+ The language provides standard arithmetic operations such as
+ addition, subtraction, multiplication, and division. It also
+ provides support for modulo arithmetic as well as operations at
+ the bit level, e.g., exclusive-or. Any binary or unary operator
+ may be extended to work with any data type. For example, the
+ addition operator (\var{+}) has been extended to work between
+ string types to permit string concatenation.
+
+ The binary and unary operators work transparently with array types.
+ For example, if \var{a} and \var{b} are arrays, then \exmp{a + b}
+ produces an array whose elements are the result of element by
+ element addition of \var{a} and \var{b}. This permits one to do
+ vector operations without explicitly looping over the array
+ indices.
+
+#%}}}
+
+\sect{Statements and Functions} #%{{{
+
+ The \slang language supports several types of looping constructs and
+ conditional statements. The looping constructs include \kw{while},
+ \kw{do...while}, \kw{for}, \kw{forever}, \kw{loop}, \kw{foreach},
+ and \kw{_for}. The conditional statements include \kw{if},
+ \kw{if-then-else}, and \kw{!if}.
+
+ User defined functions may be defined to return zero, one, or more
+ values. Functions that return zero values are similar to
+ `procedures' in languages such as PASCAL. The local variables of a
+ function are always created on a stack allowing one to create
+ recursive functions. Parameters to a function are always passed by
+ value and never by reference. However, the language supports a
+ \em{reference} data type that allows one to simulate pass by
+ reference.
+
+ Unlike many interpreted languages, \slang allows functions to be
+ dynamically loaded (function autoloading). It also provides
+ constructs specifically designed for error handling and recovery as
+ well as debugging aids (e.g., function tracebacks).
+
+ Functions and variables may be declared as private belonging to a
+ namespace associated with the compilation unit that defines the
+ function or variable. The ideas behind the namespace implementation
+ stems from the C language and should be quite familiar to any one
+ familiar with C.
+
+#%}}}
+
+\sect{Error Handling} #%{{{
+
+ The \slang language defines a construct called an \em{error-block}
+ that may be used for error handling and recovery. When a non-fatal
+ run-time error is encountered, any error blocks that have been
+ defined are executed as the run-time stack unwinds. An error block
+ can optionally clear the error and the program will continue
+ running after the statement that triggered the error. This
+ mechanism is somewhat similar to try-catch in C++.
+
+#%}}}
+
+\sect{Run-Time Library} #%{{{
+
+ Functions that compose the \slang run-time library are called
+ \em{intrinsics}. Examples of \slang intrinsic functions available
+ to every \slang application include string manipulation functions
+ such as \var{strcat}, \var{strchop}, and \var{strcmp}. The \slang
+ library also provides mathematical functions such as \var{sin},
+ \var{cos}, and \var{tan}; however, not all applications enable the
+ use of these intrinsics. For example, to conserve memory, the 16
+ bit version of the \jed editor does not provide support for any
+ mathematics other than simple integer arithmetic, whereas other
+ versions of the editor do support these functions.
+
+ Most applications embedding the languages will also provide a set of
+ application specific intrinsic functions. For example, the \jed
+ editor adds over 100 application specific intrinsic functions to
+ the language. Consult your application specific documentation to
+ see what additional intrinsics are supported.
+
+#%}}}
+
+\sect{Input/Output}
+
+ The language supports C-like stdio input/output functions such as
+ \var{fopen}, \var{fgets}, \var{fputs}, and \var{fclose}. In
+ addition it provides two functions, \var{message} and \var{error},
+ for writing to the standard output device and standard error.
+ Specific applications may provide other I/O mechanisms, e.g.,
+ the \jed editor supports I/O to files via the editor's
+ buffers.
+
+\sect{Obtaining \slang} #%{{{
+
+ Comprehensive information about the library may be obtained via the
+ World Wide Web from \tt{http://www.s-lang.org}.
+
+ \slang as well as some programs that embed it are freely available
+ via anonymous ftp in the United States from
+\begin{itemize}
+ \item \url{ftp://space.mit.edu/pub/davis}.
+\end{itemize}
+ It is also available outside the United States from the following
+ mirror sites:
+\begin{itemize}
+ \item \url{ftp://ftp.uni-stuttgart.de/pub/unix/misc/slang/}
+ \item \url{ftp://ftp.fu-berlin.de/pub/unix/news/slrn/}
+ \item \url{ftp://ftp.ntua.gr/pub/lang/slang/}
+\end{itemize}
+
+ The Usenet newsgroup \var{alt.lang.s-lang} was created for \slang
+ programmers to exchange information and share macros for the various
+ programs the embed the language. The newsgroup \var{comp.editors}
+ can be a useful resource for \slang macros for the \jed editor.
+ Similarly, \slrn users will find \var{news.software.readers} to be a
+ valuable source of information.
+
+ Finally, two mailing lists dealing with the \slang library have been
+ created:
+\begin{itemize}
+ \item \tt{slang-announce@babayaga.math.fu-berlin.de}
+ \item \tt{slang-workers@babayaga.math.fu-berlin.de}
+\end{itemize}
+ The first list is for announcements of new releases of the library, while the
+ second list is intended for those who use the library for their own code
+ development. To subscribe to the announcement list, send an email to
+ \tt{slang-announce-subscribe@babayaga.math.fu-berlin.de} and include
+ the word \tt{subscribe} in the body of the message. To subscribe to
+ the developers list, use the address
+ \tt{slang-workers-subscribe@babayaga.math.fu-berlin.de}.
+
+#%}}}
+
+#%}}}
+
+\chapter{Overview of the Language} #%{{{
+
+ This purpose of this section is to give the reader a feel for the
+ \slang language, its syntax, and its capabilities. The information
+ and examples presented in this section should be sufficient to
+ provide the reader with the necessary background to understand the
+ rest of the document.
+
+\sect{Variables and Functions} #%{{{
+
+ \slang is different from many other interpreted languages in the
+ sense that all variables and functions must be declared before they
+ can be used.
+
+ Variables are declared using the \kw{variable} keyword, e.g.,
+#v+
+ variable x, y, z;
+#v-
+ declares three variables, \var{x}, \var{y}, and \var{z}. Note the
+ semicolon at the end of the statement. \em{All \slang statements must
+ end in a semi-colon.}
+
+ Unlike compiled languages such as C, it is not necessary to specify
+ the data type of a \slang variable. The data type of a \slang
+ variable is determined upon assignment. For example, after
+ execution of the statements
+#v+
+ x = 3;
+ y = sin (5.6);
+ z = "I think, therefore I am.";
+#v-
+ \var{x} will be an integer, \var{y} will be a
+ double, and \var{z} will be a string. In fact, it is even possible
+ to re-assign \var{x} to a string:
+#v+
+ x = "x was an integer, but now is a string";
+#v-
+ Finally, one can combine variable declarations and assignments in
+ the same statement:
+#v+
+ variable x = 3, y = sin(5.6), z = "I think, therefore I am.";
+#v-
+
+ Most functions are declared using the \kw{define} keyword. A
+ simple example is
+#v+
+ define compute_average (x, y)
+ {
+ variable s = x + y;
+ return s / 2.0;
+ }
+#v-
+ which defines a function that simply computes the average of two
+ numbers and returns the result. This example shows that a function
+ consists of three parts: the function name, a parameter list, and
+ the function body.
+
+ The parameter list consists of a comma separated list of variable
+ names. It is not necessary to declare variables within a parameter
+ list; they are implicitly declared. However, all other \em{local}
+ variables used in the function must be declared. If the function
+ takes no parameters, then the parameter list must still be present,
+ but empty:
+#v+
+ define go_left_5 ()
+ {
+ go_left (5);
+ }
+#v-
+ The last example is a function that takes no arguments and returns
+ no value. Some languages such as PASCAL distinguish such objects
+ from functions that return values by calling these objects
+ \em{procedures}. However, \slang, like C, does not make such a
+ distinction.
+
+ The language permits \em{recursive} functions, i.e., functions that
+ call themselves. The way to do this in \slang is to first declare
+ the function using the form:
+\begin{tscreen}
+ define \em{function-name} ();
+\end{tscreen}
+ It is not necessary to declare a parameter list when declaring a
+ function in this way.
+
+ The most famous example of a recursive function is the factorial
+ function. Here is how to implement it using \slang:
+#v+
+ define factorial (); % declare it for recursion
+
+ define factorial (n)
+ {
+ if (n < 2) return 1;
+ return n * factorial (n - 1);
+ }
+#v-
+ This example also shows how to mix comments with code. \slang uses
+ the `\var{%}' character to start a comment and all characters from
+ the comment character to the end of the line are ignored.
+
+#%}}}
+
+\sect{Strings} #%{{{
+
+ Perhaps the most appealing feature of any interpreted language is
+ that it frees the user from the responsibility of memory management.
+ This is particularly evident when contrasting how
+ \slang handles string variables with a lower level language such as
+ C. Consider a function that concatenates three strings. An
+ example in \slang is:
+#v+
+ define concat_3_strings (a, b, c)
+ {
+ return strcat (a, strcat (b, c));
+ }
+#v-
+ This function uses the built-in
+ \var{strcat} function for concatenating two strings. In C, the
+ simplest such function would look like:
+#v+
+ char *concat_3_strings (char *a, char *b, char *c)
+ {
+ unsigned int len;
+ char *result;
+ len = strlen (a) + strlen (b) + strlen (c);
+ if (NULL == (result = (char *) malloc (len + 1)))
+ exit (1);
+ strcpy (result, a);
+ strcat (result, b);
+ strcat (result, c);
+ return result;
+ }
+#v-
+ Even this C example is misleading since none of the issues of memory
+ management of the strings has been dealt with. The \slang language
+ hides all these issues from the user.
+
+ Binary operators have been defined to work with the string data
+ type. In particular the \var{+} operator may be used to perform
+ string concatenation. That is, one can use the
+ \var{+} operator as an alternative to \var{strcat}:
+#v+
+ define concat_3_strings (a, b, c)
+ {
+ return a + b + c;
+ }
+#v-
+ See section ??? for more information about string variables.
+
+#%}}}
+
+\sect{Referencing and Dereferencing} #%{{{
+ The unary prefix operator, \var{&}, may be used to create a
+ \em{reference} to an object, which is similar to a pointer
+ in other languages. References are commonly used as a mechanism to
+ pass a function as an argument to another function as the following
+ example illustrates:
+#v+
+ define compute_functional_sum (funct)
+ {
+ variable i, s;
+
+ s = 0;
+ for (i = 0; i < 10; i++)
+ {
+ s += (@funct)(i);
+ }
+ return s;
+ }
+
+ variable sin_sum = compute_functional_sum (&sin);
+ variable cos_sum = compute_functional_sum (&cos);
+#v-
+ Here, the function \var{compute_functional_sum} applies the
+ function specified by the parameter \var{funct} to the first
+ \exmp{10} integers and returns the sum. The two statements
+ following the function definition show how the \var{sin} and
+ \var{cos} functions may be used.
+
+ Note the \var{@} operator in the definition of
+ \var{compute_functional_sum}. It is known as the \em{dereference}
+ operator and is the inverse of the reference operator.
+
+ Another use of the reference operator is in the context of the
+ \var{fgets} function. For example,
+#v+
+ define read_nth_line (file, n)
+ {
+ variable fp, line;
+ fp = fopen (file, "r");
+
+ while (n > 0)
+ {
+ if (-1 == fgets (&line, fp))
+ return NULL;
+ n--;
+ }
+ return line;
+ }
+#v-
+ uses the \var{fgets} function to read the nth line of a file.
+ In particular, a reference to the local variable \var{line} is
+ passed to \var{fgets}, and upon return \var{line} will be set to
+ the character string read by \var{fgets}.
+
+ Finally, references may be used as an alternative to multiple
+ return values by passing information back via the parameter list.
+ The example involving \var{fgets} presented above provided an
+ illustration of this. Another example is
+#v+
+ define set_xyz (x, y, z)
+ {
+ @x = 1;
+ @y = 2;
+ @z = 3;
+ }
+ variable X, Y, Z;
+ set_xyz (&X, &Y, &Z);
+#v-
+ which, after execution, results in \var{X} set to \exmp{1}, \var{Y}
+ set to \exmp{2}, and \var{Z} set to \exmp{3}. A C programmer will
+ note the similarity of \var{set_xyz} to the following C
+ implementation:
+#v+
+ void set_xyz (int *x, int *y, int *z)
+ {
+ *x = 1;
+ *y = 2;
+ *z = 3;
+ }
+#v-
+#%}}}
+
+\sect{Arrays} #%{{{
+ The \slang language supports multi-dimensional arrays of all
+ datatypes. For example, one can define arrays of references to
+ functions as well as arrays of arrays. Here are a few examples of
+ creating arrays:
+#v+
+ variable A = Integer_Type [10];
+ variable B = Integer_Type [10, 3];
+ variable C = [1, 3, 5, 7, 9];
+#v-
+ The first example creates an array of \var{10} integers and assigns
+ it to the variable \var{A}. The second example creates a 2-d array
+ of \var{30} integers arranged in \var{10} rows and \var{3} columns
+ and assigns the result to \var{B}. In the last example, an array
+ of \var{5} integers is assigned to the variable \var{C}. However,
+ in this case the elements of the array are initialized to the
+ values specified. This is known as an \em{inline-array}.
+
+ \slang also supports something called an
+ \em{range-array}. An example of such an array is
+#v+
+ variable C = [1:9:2];
+#v-
+ This will produce an array of 5 integers running from \exmp{1}
+ through \exmp{9} in increments of \exmp{2}.
+
+ Arrays are passed by reference to functions and never by value.
+ This permits one to write functions which can initialize arrays.
+ For example,
+#v+
+ define init_array (a)
+ {
+ variable i, imax;
+
+ imax = length (a);
+ for (i = 0; i < imax; i++)
+ {
+ a[i] = 7;
+ }
+ }
+
+ variable A = Integer_Type [10];
+ init_array (A);
+#v-
+ creates an array of \var{10} integers and initializes all its
+ elements to \var{7}.
+
+ There are more concise ways of accomplishing the result of the
+ previous example. These include:
+#v+
+ variable A = [7, 7, 7, 7, 7, 7, 7, 7, 7, 7];
+ variable A = Integer_Type [10]; A[[0:9]] = 7;
+ variable A = Integer_Type [10]; A[*] = 7;
+#v-
+ The second and third methods use an array of indices to index the array
+ \var{A}. In the second, the range of indices has been explicitly
+ specified, whereas the third example uses a wildcard form. See
+ section ??? for more information about array indexing.
+
+ Although the examples have pertained to integer arrays, the fact is
+ that \slang arrays can be of any type, e.g.,
+#v+
+ variable A = Double_Type [10];
+ variable B = Complex_Type [10];
+ variable C = String_Type [10];
+ variable D = Ref_Type [10];
+#v-
+ create \var{10} element arrays of double, complex, string, and
+ reference types, respectively. The last example may be used to
+ create an array of functions, e.g.,
+#v+
+ D[0] = &sin;
+ D[1] = &cos;
+#v-
+
+ The language also defines unary, binary, and mathematical
+ operations on arrays. For example, if \var{A} and \var{B} are
+ integer arrays, then \exmp{A + B} is an array whose elements are
+ the sum of the elements of \var{A} and \var{B}. A trivial example
+ that illustrates the power of this capability is
+#v+
+ variable X, Y;
+ X = [0:2*PI:0.01];
+ Y = 20 * sin (X);
+#v-
+ which is equivalent to the highly simplified C code:
+#v+
+ double *X, *Y;
+ unsigned int i, n;
+
+ n = (2 * PI) / 0.01 + 1;
+ X = (double *) malloc (n * sizeof (double));
+ Y = (double *) malloc (n * sizeof (double));
+ for (i = 0; i < n; i++)
+ {
+ X[i] = i * 0.01;
+ Y[i] = 20 * sin (X[i]);
+ }
+#v-
+
+
+#%}}}
+
+\sect{Structures and User-Defined Types} #%{{{
+
+ A \em{structure} is similar to an array in the sense that it is a
+ container object. However, the elements of an array must all be of
+ the same type (or of \var{Any_Type}), whereas a structure is
+ heterogeneous. As an example, consider
+#v+
+ variable person = struct
+ {
+ first_name, last_name, age
+ };
+ variable bill = @person;
+ bill.first_name = "Bill";
+ bill.last_name = "Clinton";
+ bill.age = 51;
+#v-
+ In this example a structure consisting of the three fields has been
+ created and assigned to the variable \var{person}. Then an
+ \em{instance} of this structure has been created using the
+ dereference operator and assigned to \var{bill}. Finally, the
+ individual fields of \var{bill} were initialized. This is an
+ example of an \em{anonymous} structure.
+
+ A \em{named} structure is really a new data type and may be created
+ using the \kw{typedef} keyword:
+#v+
+ typedef struct
+ {
+ first_name, last_name, age
+ }
+ Person_Type;
+
+ variable bill = @Person_Type;
+ bill.first_name = "Bill";
+ bill.last_name = "Clinton";
+ bill.age = 51;
+#v-
+ The big advantage of creating a new type is that one can go on to
+ create arrays of the data type
+#v+
+ variable People = Person_Type [100];
+ People[0].first_name = "Bill";
+ People[1].first_name = "Hillary";
+#v-
+
+ The creation and initialization of a structure may be facilitated
+ by a function such as
+#v+
+ define create_person (first, last, age)
+ {
+ variable person = @Person_Type;
+ person.first_name = first;
+ person.last_name = last;
+ person.age = age;
+ return person;
+ }
+ variable Bill = create_person ("Bill", "Clinton", 51);
+#v-
+
+ Other common uses of structures is the creation of linked lists,
+ binary trees, etc. For more information about these and other
+ features of structures, see section ???.
+
+
+#%}}}
+
+\sect{Namespaces}
+
+ In addition to the global namespace, each compilation unit (e.g., a
+ file) is given a private namespace. A variable or function name
+ that is declared using the \var{static} keyword will be placed in
+ the private namespace associated with compilation unit. For
+ example,
+#v+
+ variable i;
+ static variable i;
+#v-
+ defines two variables called \var{i}. The first declaration
+ defines \var{i} in the global namespace, but the second declaration
+ defines \var{i} in the private namespace.
+
+ The \exmp{->} operator may be used in conjunction with the name of
+ the namespace to access objects in the name space. In the above
+ example, to access the variable \var{i} in the global namespace,
+ one would use \exmp{Global->i}. Unless otherwise specified, a
+ private namespace has no name and its objects may not be accessed
+ from outside the compilation unit. However, the \var{implements}
+ function may be used give the private namespace a name, allowing
+ access to its objects. For example, if the file \exmp{t.sl} contains
+#v+
+ implements ("A");
+ static variable i;
+#v-
+ then another file may access the variable \var{i} via \exmp{A->i}.
+
+#%}}}
+
+\chapter{Data Types and Literal Constants} #%{{{
+
+ The current implementation of the \slang language permits up to 256
+ distinct data types, including predefined data types such as integer and
+ floating point, as well as specialized applications specific data
+ types. It is also possible to create new data types in the
+ language using the \kw{typedef} mechanism.
+
+ Literal constants are objects such as the integer \exmp{3} or the
+ string \exmp{"hello"}. The actual data type given to a literal
+ constant depends upon the syntax of the constant. The following
+ sections describe the syntax of literals of specific data types.
+
+\sect{Predefined Data Types} #%{{{
+
+ The current version of \slang defines integer, floating point,
+ complex, and string types. It also defines special purpose data
+ types such as \var{Null_Type}, \var{DataType_Type}, and
+ \var{Ref_Type}. These types are discussed below.
+
+\sect1{Integers} #%{{{
+
+ The \slang language supports both signed and unsigned characters,
+ short integer, long integer, and plain integer types. On most 32
+ bit systems, there is no difference between an integer and a long
+ integer; however, they may differ on 16 and 64 bit systems.
+ Generally speaking, on a 16 bit system, plain integers are 16 bit
+ quantities with a range of -32767 to 32767. On a 32 bit system,
+ plain integers range from -2147483648 to 2147483647.
+
+ An plain integer \em{literal} can be specified in one of several ways:
+\begin{itemize}
+\item As a decimal (base 10) integer consisting of the characters
+ \var{0} through \var{9}, e.g., \var{127}. An integer specified
+ this way cannot begin with a leading \var{0}. That is,
+ \var{0127} is \em{not} the same as \var{127}.
+
+\item Using hexadecimal (base 16) notation consisting of the characters
+ \var{0} to \var{9} and \var{A} through \var{F}. The hexadecimal
+ number must be preceded by the characters \var{0x}. For example,
+ \var{0x7F} specifies an integer using hexadecimal notation and has
+ the same value as decimal \var{127}.
+
+\item In Octal notation using characters \var{0} through \var{7}. The Octal
+ number must begin with a leading \var{0}. For example,
+ \var{0177} and \var{127} represent the same integer.
+
+ Short, long, and unsigned types may be specified by using the
+ proper suffixes: \var{L} indicates that the integer is a long
+ integer, \var{h} indicates that the integer is a short integer, and
+ \var{U} indicates that it is unsigned. For example, \exmp{1UL}
+ specifies an unsigned long integer.
+
+ Finally, a character literal may be specified using a notation
+ containing a character enclosed in single quotes as \exmp{'a'}.
+ The value of the character specified this way will lie in the
+ range 0 to 256 and will be determined by the ASCII value of the
+ character in quotes. For example,
+#v+
+ i = '0';
+#v-
+ assigns to \var{i} the character 48 since the \exmp{'0'} character
+ has an ASCII value of 48.
+\end{itemize}
+
+ Any integer may be preceded by a minus sign to indicate that it is a
+ negative integer.
+
+#%}}}
+
+\sect1{Floating Point Numbers} #%{{{
+
+ Single and double precision floating point literals must contain either a
+ decimal point or an exponent (or both). Here are examples of
+ specifying the same double precision point number:
+#v+
+ 12. 12.0 12e0 1.2e1 120e-1 .12e2 0.12e2
+#v-
+ Note that \var{12} is \em{not} a floating point number since it
+ contains neither a decimal point nor an exponent. In fact,
+ \var{12} is an integer.
+
+ One may append the \var{f} character to the end of the number to
+ indicate that the number is a single precision literal.
+
+#%}}}
+
+\sect1{Complex Numbers} #%{{{
+
+ The language implements complex numbers as a pair of double
+ precision floating point numbers. The first number in the pair
+ forms the \em{real} part, while the second number forms the
+ \em{imaginary} part. That is, a complex number may be regarded as the
+ sum of a real number and an imaginary number.
+
+ Strictly speaking, the current implementation of the \slang does
+ not support generic complex literals. However, it does support
+ imaginary literals and a more generic complex number with a non-zero
+ real part may be constructed from the imaginary literal via
+ addition of a real number.
+
+ An imaginary literal is specified in the same way as a floating
+ point literal except that \var{i} or \var{j} is appended. For
+ example,
+#v+
+ 12i 12.0i 12e0j
+#v-
+ all represent the same imaginary number. Actually, \var{12i} is
+ really an imaginary integer except that \slang automatically
+ promotes it to a double precision imaginary number.
+
+ A more generic complex number may be constructed from an imaginary
+ literal via addition, e.g.,
+#v+
+ 3.0 + 4.0i
+#v-
+ produces a complex number whose real part is \exmp{3.0} and whose
+ imaginary part is \exmp{4.0}.
+
+ The intrinsic functions \var{Real} and \var{Imag} may be used to
+ retrieve the real and imaginary parts of a complex number,
+ respectively.
+
+#%}}}
+
+\sect1{Strings} #%{{{
+
+ A string literal must be enclosed in double quotes as in:
+#v+
+ "This is a string".
+#v-
+ Although there is no imposed limit on the length of a string,
+ string literals must be less than 256 characters in length. It is
+ possible to go beyond this limit by string concatenation, e.g.,
+#v+
+ "This is the first part of a long string"
+ + "and this is the second half"
+#v-
+ Any character except a newline (ASCII 10) or the null character
+ (ASCII 0) may appear explicitly in a string literal. However,
+ these characters may be used implicitly using the mechanism
+ described below.
+
+ The backslash character is a special character and is used to
+ include other special characters (such as a newline character) in
+ the string. The special characters recognized are:
+#v+
+ \" -- double quote
+ \' -- single quote
+ \\ -- backslash
+ \a -- bell character (ASCII 7)
+ \t -- tab character (ASCII 9)
+ \n -- newline character (ASCII 10)
+ \e -- escape character (ASCII 27)
+ \xhhh -- character expressed in HEXADECIMAL notation
+ \ooo -- character expressed in OCTAL notation
+ \dnnn -- character expressed in DECIMAL
+#v-
+ For example, to include the double quote character as part of the
+ string, it must be preceded by a backslash character, e.g.,
+#v+
+ "This is a \"quote\""
+#v-
+ Similarly, the next illustrates how a newline character may be
+ included:
+#v+
+ "This is the first line\nand this is the second"
+#v-
+#%}}}
+
+
+\sect1{Null_Type}
+
+ Objects of type \var{Null_Type} can have only one value:
+ \var{NULL}. About the only thing that you can do with this data
+ type is to assign it to variables and test for equality with
+ other objects. Nevertheless, \var{Null_Type} is an important and
+ extremely useful data type. Its main use stems from the fact that
+ since it can be compared for equality with any other data type, it
+ is ideal to represent the value of an object which does not yet
+ have a value, or has an illegal value.
+
+ As a trivial example of its use, consider
+#v+
+ define add_numbers (a, b)
+ {
+ if (a == NULL) a = 0;
+ if (b == NULL) b = 0;
+ return a + b;
+ }
+ variable c = add_numbers (1, 2);
+ variable d = add_numbers (1, NULL);
+ variable e = add_numbers (1,);
+ variable f = add_numbers (,);
+#v-
+ It should be clear that after these statements have been executed,
+ \var{c} will have a value of \exmp{3}. It should also be clear
+ that \var{d} will have a value of \exmp{1} because \var{NULL} has
+ been passed as the second parameter. One feature of the language
+ is that if a parameter has been omitted from a function call, the
+ variable associated with that parameter will be set to \var{NULL}.
+ Hence, \var{e} and \var{f} will be set to \exmp{1} and \exmp{0},
+ respectively.
+
+ The \var{Null_Type} data type also plays an important role in the
+ context of \em{structures}.
+
+\sect1{Ref_Type}
+ Objects of \var{Ref_Type} are created using the unary
+ \em{reference} operator \var{&}. Such objects may be
+ \em{dereferenced} using the dereference operator \var{@}. For
+ example,
+#v+
+ variable sin_ref = &sin;
+ variable y = (@sin_ref) (1.0);
+#v-
+ creates a reference to the \var{sin} function and assigns it to
+ \var{sin_ref}. The second statement uses the dereference operator
+ to call the function that \var{sin_ref} references.
+
+ The \var{Ref_Type} is useful for passing functions as arguments to
+ other functions, or for returning information from a function via
+ its parameter list. The dereference operator is also used to create
+ an instance of a structure. For these reasons, further discussion
+ of this important type can be found in section ??? and section ???.
+
+\sect1{Array_Type and Struct_Type}
+
+ Variables of type \var{Array_Type} and \var{Struct_Type} are known
+ as \em{container objects}. They are much more complicated than the
+ simple data types discussed so far and each obeys a special syntax.
+ For these reasons they are discussed in a separate chapters.
+ See ???.
+
+\sect1{DataType_Type Type} #%{{{
+
+ \slang defines a type called \var{DataType_Type}. Objects of
+ this type have values that are type names. For example, an integer
+ is an object of type \var{Integer_Type}. The literals of
+ \var{DataType_Type} include:
+#v+
+ Char_Type (signed character)
+ UChar_Type (unsigned character)
+ Short_Type (short integer)
+ UShort_Type (unsigned short integer)
+ Integer_Type (plain integer)
+ UInteger_Type (plain unsigned integer)
+ Long_Type (long integer)
+ ULong_Type (unsigned long integer)
+ Float_Type (single precision real)
+ Double_Type (double precision real)
+ Complex_Type (complex numbers)
+ String_Type (strings, C strings)
+ BString_Type (binary strings)
+ Struct_Type (structures)
+ Ref_Type (references)
+ Null_Type (NULL)
+ Array_Type (arrays)
+ DataType_Type (data types)
+#v-
+ as well as the names of any other types that an application
+ defines.
+
+ The built-in function \var{typeof} returns the data type of
+ its argument, i.e., a \var{DataType_Type}. For instance
+ \exmp{typeof(7)} returns \var{Integer_Type} and
+ \var{typeof(Integer_Type)} returns \var{DataType_Type}. One can use this
+ function as in the following example:
+#v+
+ if (Integer_Type == typeof (x)) message ("x is an integer");
+#v-
+ The literals of \var{DataType_Type} have other uses as well. One
+ of the most common uses of these literals is to create arrays, e.g.,
+#v+
+ x = Complex_Type [100];
+#v-
+ creates an array of \exmp{100} complex numbers and assigns it to
+ \var{x}.
+#%}}}
+
+#%}}}
+
+\sect{Typecasting: Converting from one Type to Another}
+
+ Occasionally, it is necessary to convert from one data type to
+ another. For example, if you need to print an object as a string,
+ it may be necessary to convert it to a \var{String_Type}. The
+ \var{typecast} function may be used to perform such conversions.
+ For example, consider
+#v+
+ variable x = 10, y;
+ y = typecast (x, Double_Type);
+#v-
+ After execution of these statements, \var{x} will have the integer
+ value \exmp{10} and \var{y} will have the double precision floating
+ point value \exmp{10.0}. If the object to be converted is an
+ array, the \var{typecast} function will act upon all elements of
+ the array. For example,
+#v+
+ variable x = [1:10]; % Array of integers
+ variable y = typecast (x, Double_Type);
+#v-
+ will create an array of \exmp{10} double precision values and
+ assign it to \var{y}. One should also realize that it is not
+ always possible to perform a typecast. For example, any attempt to
+ convert an \var{Integer_Type} to a \var{Null_Type} will result in a
+ run-time error.
+
+ Often the interpreter will perform implicit type conversions as necessary
+ to complete calculations. For example, when multiplying an
+ \var{Integer_Type} with a \var{Double_Type}, it will convert the
+ \var{Integer_Type} to a \var{Double_Type} for the purpose of the
+ calculation. Thus, the example involving the conversion of an
+ array of integers to an array of doubles could have been performed
+ by multiplication by \exmp{1.0}, i.e.,
+#v+
+ variable x = [1:10]; % Array of integers
+ variable y = 1.0 * x;
+#v-
+
+ The \var{string} intrinsic function is similar to the typecast
+ function except that it converts an object to a string
+ representation. It is important to understand that a typecast from
+ some type to \var{String_Type} is \em{not} the same as converting
+ an object to its string operation. That is,
+ \exmp{typecast(x,String_Type)} is not equivalent to
+ \exmp{string(x)}. The reason for this is that when given an array,
+ the \var{typecast} function acts on each element of the array to
+ produce another array, whereas the \var{string} function produces a
+ a string.
+
+ The \var{string} function is useful for printing the value of an
+ object. This use is illustrated in the following simple example:
+#v+
+ define print_object (x)
+ {
+ message (string (x));
+ }
+#v-
+ Here, the \var{message} function has been used because it writes a
+ string to the display. If the \var{string} function was not used
+ and the \var{message} function was passed an integer, a
+ type-mismatch error would have resulted.
+
+#%}}}
+
+\chapter{Identifiers} #%{{{
+
+ The names given to variables, functions, and data types are called
+ \em{identifiers}. There are some restrictions upon the actual
+ characters that make up an identifier. An identifier name must
+ start with a letter (\var{[A-Za-z]}), an underscore character, or a
+ dollar sign. The rest of the characters in the name can be any
+ combination of letters, digits, dollar signs, or underscore
+ characters. However, all identifiers whose name begins with two
+ underscore characters are reserved for internal use by the
+ interpreter and declarations of objects with such names should be
+ avoided.
+
+ Examples of valid identifiers include:
+#v+
+ mary _3 _this_is_ok
+ a7e1 $44 _44$_Three
+#v-
+ However, the following are not legal:
+#v+
+ 7abc 2e0 #xx
+#v-
+ In fact, \exmp{2e0} actually specifies the real number
+ \exmp{2.0}.
+
+ Although the maximum length of identifiers is unspecified by the
+ language, the length should be kept below \exmp{64} characters.
+
+ The following identifiers are reserved by the language for use as
+ keywords:
+#v+
+ !if _for do mod sign xor
+ ERROR_BLOCK abs do_while mul2 sqr public
+ EXIT_BLOCK and else not static private
+ USER_BLOCK0 andelse exch or struct
+ USER_BLOCK1 break for orelse switch
+ USER_BLOCK2 case foreach pop typedef
+ USER_BLOCK3 chs forever return using
+ USER_BLOCK4 continue if shl variable
+ __tmp define loop shr while
+#v-
+ In addition, the next major \slang release (v2.0) will reserve
+ \exmp{try} and \exmp{catch}, so it is probably a good idea to avoid
+ those words until then.
+
+#%}}}
+
+\chapter{Variables} #%{{{
+
+ A variable must be declared before it can be used, otherwise an
+ undefined name error will be generated. A variable is declared
+ using the \kw{variable} keyword, e.g,
+#v+
+ variable x, y, z;
+#v-
+ declares three variables, \exmp{x}, \exmp{y}, and \exmp{z}. This
+ is an example of a variable declaration statement, and like all
+ statements, it must end in a semi-colon.
+
+ Variables declared this way are untyped and inherit a type upon
+ assignment. The actual type checking is performed at run-time. For
+ example,
+#v+
+ x = "This is a string";
+ x = 1.2;
+ x = 3;
+ x = 2i;
+#v-
+ results in x being set successively to a string, a float, an
+ integer, and to a complex number (\exmp{0+2i}). Any attempt to use
+ a variable before it has acquired a type will result in an
+ uninitialized variable error.
+
+ It is legal to put executable code in a variable declaration list.
+ That is,
+#v+
+ variable x = 1, y = sin (x);
+#v-
+ are legal variable declarations. This also provides a convenient way
+ of initializing a variable.
+
+ Variables are classified as either \em{global} or \em{local}. A
+ variable declared inside a function is said to be local and has no
+ meaning outside the function. A variable is said to be global if
+ it was declared outside a function. Global variables are further
+ classified as being \var{public}, \var{static}, or \var{private},
+ according to the name space where they were defined.
+ See chapter ??? for more information about name spaces.
+
+ The following global variables are predefined by the language and
+ are mainly used as convenience variables:
+#v+
+ $0 $1 $2 $3 $4 $5 $6 $7 $8 $9
+#v-
+
+ An \em{intrinsic} variable is another type of global variable.
+ Such variables have a definite type which cannot be altered.
+ Variables of this type may also be defined to be read-only, or
+ constant variables. An example of an intrinsic variable is
+ \var{PI} which is a read-only double precision variable with a value
+ of approximately \exmp{3.14159265358979323846}.
+
+#%}}}
+
+\chapter{Operators} #%{{{
+
+ \slang supports a variety of operators that are grouped into three
+ classes: assignment operators, binary operators, and unary operators.
+
+ An assignment operator is used to assign a value to a variable.
+ They will be discussed more fully in the context of the assignment
+ statement in section ???.
+
+ An unary operator acts only upon a single quantity while a binary
+ operation is an operation between two quantities. The boolean
+ operator \var{not} is an example of an unary operator. Examples of
+ binary operators include the usual arithmetic operators
+ \var{+}, \var{-}, \var{*}, and \var{/}. The operator given by
+ \var{-} can be either an unary operator (negation) or a binary operator
+ (subtraction); the actual operation is determined from the context
+ in which it is used.
+
+ Binary operators are used in algebraic forms, e.g., \exmp{a + b}.
+ Unary operators fall in one of two classes: postfix-unary or
+ prefix-unary. For example, in the expression \exmp{-x}, the minus
+ sign is a prefix-unary operator.
+
+ Not all data types have binary or unary operations defined. For
+ example, while \var{String_Type} objects support the \var{+}
+ operator, they do not admit the \var{*} operator.
+
+\sect{Unary Operators}
+
+ The \bf{unary} operators operate only upon a single operand. They
+ include: \var{not}, \var{~}, \var{-}, \var{@}, \var{&}, as well as the
+ increment and decrement operators \var{++} and \var{--},
+ respectively.
+
+ The boolean operator \var{not} acts only upon integers and produces
+ \var{0} if its operand is non-zero, otherwise it produces \var{1}.
+
+ The bit-level not operator \var{~} performs a similar function,
+ except that it operates on the individual bits of its integer
+ operand.
+
+ The arithmetic negation operator \var{-} is the most well-known
+ unary operator. It simply reverses the sign of its operand.
+
+ The reference (\var{&}) and dereference (\var{@}) operators will be
+ discussed in greater detail in section ???. Similarly, the
+ increment (\var{++}) and decrement (\var{--}) operators will be
+ discussed in the context of the assignment operator.
+
+\sect{Binary Operators} #%{{{
+
+ The binary operators may be grouped according to several classes:
+ arithmetic operators, relational operators, boolean operators, and
+ bitwise operators.
+
+ All binary and unary operators may be overloaded. For example, the
+ arithmetic plus operator has been overloaded by the
+ \var{String_Type} data type to permit concatenation between strings.
+
+\sect1{Arithmetic Operators} #%{{{
+
+ The arithmetic operators include \var{+}, \var{-}, \var{*}, \var{/},
+ which perform addition, subtraction, multiplication, and division,
+ respectively. In addition to these, \slang supports the \var{mod}
+ operator as well as the power operator \var{^}.
+
+ The data type of the result produced by the use of one of these
+ operators depends upon the data types of the binary participants.
+ If they are both integers, the result will be an integer. However,
+ if the operands are not of the same type, they will be converted to
+ a common type before the operation is performed. For example, if
+ one is a floating point value and the other is an integer, the
+ integer will be converted to a float. In general, the promotion
+ from one type to another is such that no information is lost, if
+ possible. As an example, consider the expression \exmp{8/5} which
+ indicates division of the integer \var{8} by the integer \var{5}.
+ The result will be the integer \var{1} and \em{not} the floating
+ point value \var{1.6}. However, \exmp{8/5.0} will produce
+ \var{1.6} because \exmp{5.0} is a floating point number.
+
+#%}}}
+
+\sect1{Relational Operators} #%{{{
+
+ The relational operators are \var{>}, \var{>=}, \var{<}, \var{<=},
+ \var{==}, and \var{!=}. These perform the comparisons greater
+ than, greater than or equal, less than, less than or equal, equal,
+ and not equal, respectively. The result of one of these
+ comparisons is the integer \var{1} if the comparison is true, or
+ \var{0} if the comparison is false. For example, \exmp{6 >= 5}
+ returns \var{1}, but \var{6 == 5} produces
+ \var{0}.
+
+#%}}}
+
+\sect1{Boolean Operators} #%{{{
+ There are only two boolean binary operators: \var{or} and
+ \var{and}. These operators are defined only for integers and
+ produce an integer result. The \var{or} operator returns \var{1}
+ if either of its operands are non-zero, otherwise it produces
+ \var{0}. The \var{and} operator produces \var{1} if and only if
+ both its operands are non-zero, otherwise it produces \var{0}.
+
+ Neither of these operators perform the so-called boolean
+ short-circuit evaluation. For example, consider the expression:
+#v+
+ (x != 0) and (1/x > 10)
+#v-
+ Here, if \var{x} were to have a value of zero, a division by zero error
+ would occur because even though \var{x!=0} evaluates to zero, the
+ \var{and} operator is not short-circuited and the \var{1/x} expression
+ would still be evaluated. Although these operators are not
+ short-circuited, \slang does have another mechanism of performing
+ short-circuit boolean evaluation via the \kw{orelse} and
+ \kw{andelse} expressions. See below for information about these
+ constructs.
+
+#%}}}
+
+\sect1{Bitwise Operators} #%{{{
+
+ The bitwise binary operators are defined only with integer operands
+ and are used for bit-level operations. Operators that fall in this
+ class include \var{&}, \var{|}, \var{shl}, \var{shr}, and
+ \var{xor}. The \var{&} operator performs a boolean AND operation
+ between the corresponding bits of the operands. Similarly, the
+ \var{|} operator performs the boolean OR operation on the bits.
+ The bit-shifting operators \var{shl} and \var{shr} shift the bits
+ of the first operand by the number given by the second operand to
+ the left or right, respectively. Finally, the \var{xor} performs
+ an EXCLUSIVE-OR operation.
+
+ These operators are commonly used to manipulate variables whose
+ individual bits have distinct meanings. In particular, \var{&} is
+ usually used to test bits, \var{|} can be used to set bits, and
+ \var{xor} may be used to flip a bit.
+
+ As an example of using \var{&} to perform tests on bits, consider
+ the following: The \jed text editor stores some of the information
+ about a buffer in a bitmapped integer variable. The value of this
+ variable may be retrieved using the \jed intrinsic function
+ \var{getbuf_info}, which actually returns four quantities: the
+ buffer flags, the name of the buffer, directory name, and file
+ name. For the purposes of this section, only the buffer flags are
+ of interest and can be retrieved via a function such as
+#v+
+ define get_buffer_flags ()
+ {
+ variable flags;
+ (,,,flags) = getbuf_info ();
+ return flags;
+ }
+#v-
+ The buffer flags is a bitmapped quantity where the 0th bit
+ indicates whether or not the buffer has been modified, the first
+ bit indicates whether or not autosave has been enabled for the
+ buffer, and so on. Consider for the moment the task of determining
+ if the buffer has been modified. This can be
+ determined by looking at the zeroth bit, if it is \var{0} the
+ buffer has not been modified, otherwise it has. Thus we can create
+ the function,
+#v+
+ define is_buffer_modified ()
+ {
+ variable flags = get_buffer_flags ();
+ return (flags & 1);
+ }
+#v-
+ where the integer \exmp{1} has been used since it has all of its
+ bits set to \var{0}, except for the zeroth one, which is set to
+ \var{1}. (At this point, it should also be apparent that bits are
+ numbered from zero, thus an \var{8} bit integer consists of bits
+ \var{0} to \var{7}, where \var{0} is the least significant bit and
+ \var{7} is the most significant one.) Similarly, we can create another
+ function
+#v+
+ define is_autosave_on ()
+ {
+ variable flags = get_buffer_flags ();
+ return (flags & 2);
+ }
+#v-
+ to determine whether or not autosave has been turned on for the
+ buffer.
+
+ The \var{shl} operator may be used to form the integer with only
+ the \em{nth} bit set. For example, \exmp{1 shl 6} produces an
+ integer with all bits set to zero except the sixth bit, which is
+ set to one. The following example exploits this fact:
+#v+
+ define test_nth_bit (flags, nth)
+ {
+ return flags & (1 shl nth);
+ }
+#v-
+
+#%}}}
+
+\sect1{Namespace operator}
+ The operator \var{->} is used to in conjunction with the name of a
+ namespace to access an object within the namespace. For example,
+ if \exmp{A} is the name of a namespace containing the variable
+ \var{v}, then \exmp{A->v} refers to that variable.
+
+\sect1{Operator Precedence}
+
+\sect1{Binary Operators and Functions Returning Multiple Values} #%{{{
+ Care must be exercised when using binary operators with an operand
+ the returns multiple values. In fact, the current implementation
+ of the \slang language will produce incorrect results if both
+ operands of a binary expression return multiple values. \em{At
+ most, only one of operands of a binary expression can return
+ multiple values, and that operand must be the first one, not the
+ second.} For example,
+#v+
+ define read_line (fp)
+ {
+ variable line, status;
+
+ status = fgets (&line, fp);
+ if (status == -1)
+ return -1;
+ return (line, status);
+ }
+#v-
+ defines a function, \var{read_line} that takes a single argument, a
+ handle to an open file, and returns one or two values, depending
+ upon the return value of \var{fgets}. Now consider
+#v+
+ while (read_line (fp) > 0)
+ {
+ text = ();
+ % Do something with text
+ .
+ .
+ }
+#v-
+ Here the relational binary operator \var{>} forms a comparison
+ between one of the return values (the one at the top of the stack)
+ and \var{0}. In accordance with the above rule, since \var{read_line}
+ returns multiple values, it occurs as the left binary operand.
+ Putting it on the right as in
+#v+
+ while (0 < read_line (fp)) % Incorrect
+ {
+ text = ();
+ % Do something with text
+ .
+ .
+ }
+#v-
+ violates the rule and will result in the wrong answer.
+
+#%}}}
+
+#%}}}
+
+\sect{Mixing Integer and Floating Point Arithmetic}
+
+ If a binary operation (\var{+}, \var{-}, \var{*} , \var{/}) is
+ performed on two integers, the result is an integer. If at least
+ one of the operands is a float, the other is converted to float and
+ the result is float. For example:
+#v+
+ 11 / 2 --> 5 (integer)
+ 11 / 2.0 --> 5.5 (float)
+ 11.0 / 2 --> 5.5 (float)
+ 11.0 / 2.0 --> 5.5 (float)
+#v-
+ Finally note that only integers may be used as array indices,
+ loop control variables, and bit operations. The conversion
+ functions, \var{int} and \var{float}, may be used convert between
+ floats and ints where appropriate, e.g.,
+#v+
+ int (1.5) --> 1 (integer)
+ float(1.5) --> 1.5 (float)
+ float (1) --> 1.0 (float)
+#v-
+
+\sect{Short Circuit Boolean Evaluation}
+
+ The boolean operators \var{or} and \var{and} \em{are not short
+ circuited} as they are in some languages. \slang uses
+ \var{orelse} and \var{andelse} expressions for short circuit boolean
+ evaluation. However, these are not binary operators. Expressions
+ of the form:
+\begin{tscreen}
+ \em{expr-1} and \em{expr-2} and ... \em{expr-n}
+\end{tscreen}
+ can be replaced by the short circuited version using \var{andelse}:
+\begin{tscreen}
+ andelse {\em{expr-1}} {\em{expr-2}} ... {\em{expr-n}}
+\end{tscreen}
+ A similar syntax holds for the \var{orelse} operator. For example, consider
+ the statement:
+#v+
+ if ((x != 0) and (1/x > 10)) do_something ();
+#v-
+ Here, if \var{x} were to have a value of zero, a division by zero error
+ would occur because even though \var{x!=0} evaluates to zero, the
+ \var{and} operator is not short circuited and the \var{1/x} expression
+ would be evaluated causing division by zero. For this case, the
+ \var{andelse} expression could be used to avoid the problem:
+#v+
+ if (andelse
+ {x != 0}
+ {1 / x > 10}) do_something ();
+#v-
+
+#%}}}
+
+\chapter{Statements} #%{{{
+
+ Loosely speaking, a \em{statement} is composed of \em{expressions}
+ that are grouped according to the syntax or grammar of the language
+ to express a complete computation. Statements are analogous to
+ sentences in a human language and expressions are like phrases.
+ All statements in the \slang language must end in a semi-colon.
+
+ A statement that occurs within a function is executed only during
+ execution of the function. However, statements that occur outside
+ the context of a function are evaluated immediately.
+
+ The language supports several different types of statements such as
+ assignment statements, conditional statements, and so forth. These
+ are described in detail in the following sections.
+
+\sect{Variable Declaration Statements}
+ Variable declarations were already discussed in chapter ???. For
+ the sake of completeness, a variable declaration is a statement of
+ the form
+\begin{tscreen}
+ variable \em{variable-declaration-list} ;
+\end{tscreen}
+ where the \em{variable-declaration-list} is a comma separated list
+ of one or more variable names with optional initializations, e.g.,
+#v+
+ variable x, y = 2, z;
+#v-
+\sect{Assignment Statements} #%{{{
+
+ Perhaps the most well known form of statement is the \em{assignment
+ statement}. Statements of this type consist of a left-hand side,
+ an assignment operator, and a right-hand side. The left-hand side
+ must be something to which an assignment can be performed. Such
+ an object is called an \em{lvalue}.
+
+ The most common assignment operator is the simple assignment
+ operator \var{=}. Simple of its use include
+#v+
+ x = 3;
+ x = some_function (10);
+ x = 34 + 27/y + some_function (z);
+ x = x + 3;
+#v-
+ In addition to the simple assignment operator, \slang
+ also supports the assignment operators \var{+=} and \var{-=}.
+ Internally, \slang transforms
+#v+
+ a += b;
+#v-
+ to
+#v+
+ a = a + b;
+#v-
+ Similarly, \exmp{a -= b} is transformed to \exmp{a = a - b}. It is
+ extremely important to realize that, in general, \exmp{a+b} is not
+ equal to \exmp{b+a}. This means that \exmp{a+=b} is not the same
+ as \exmp{a=b+a}. As an example consider
+#v+
+ a = "hello"; a += "world";
+#v-
+ After execution of these two statements, \var{a} will have the
+ value \exmp{"helloworld"} and not \exmp{"worldhello"}.
+
+ Since adding or subtracting \exmp{1} from a variable is quite
+ common, \slang also supports the unary increment and decrement
+ operators \exmp{++}, and \exmp{--}, respectively. That is, for
+ numeric data types,
+#v+
+ x = x + 1;
+ x += 1;
+ x++;
+#v-
+ are all equivalent. Similarly,
+#v+
+ x = x - 1;
+ x -= 1;
+ x--;
+#v-
+ are also equivalent.
+
+ Strictly speaking, \var{++} and \var{--} are unary operators. When
+ used as \var{x++}, the \var{++} operator is said to be a
+ \em{postfix-unary} operator. However, when used as \var{++x} it is
+ said to be a \em{prefix-unary} operator. The current
+ implementation does not distinguish between the two forms, thus
+ \var{x++} and \var{++x} are equivalent. The reason for this
+ equivalence is \em{that assignment expressions do not return a value in
+ the \slang language} as they do in C. Thus one should exercise care
+ and not try to write C-like code such as
+#v+
+ x = 10;
+ while (--x) do_something (x); % Ok in C, but not in S-Lang
+#v-
+ The closest valid \slang form involves a \em{comma-expression}:
+#v+
+ x = 10;
+ while (x--, x) do_something (x); % Ok in S-Lang and in C
+#v-
+
+ \slang also supports a \em{multiple-assignment} statement. It is
+ discussed in detail in section ???.
+
+#%}}}
+
+\sect{Conditional and Looping Statements} #%{{{
+
+ \slang supports a wide variety of conditional and looping
+ statements. These constructs operate on statements grouped together
+ in \em{blocks}. A block is a sequence of \slang statements enclosed
+ in braces and may contain other blocks. However, a block cannot
+ include function declarations. In the following,
+ \em{statement-or-block} refers to either a single
+ \slang statement or to a block of statements, and
+ \em{integer-expression} is an integer-valued expression.
+ \em{next-statement} represents the statement following the form
+ under discussion.
+
+\sect1{Conditional Forms} #%{{{
+\sect2{if}
+ The simplest condition statement is the \kw{if} statement. It
+ follows the syntax
+\begin{tscreen}
+ if (\em{integer-expression}) \em{statement-or-block}
+ \em{next-statement}
+\end{tscreen}
+ If \em{integer-expression} evaluates to a non-zero result, then the
+ statement or group of statements implied \em{statement-or-block}
+ will get executed. Otherwise, control will proceed to
+ \em{next-statement}.
+
+ An example of the use of this type of conditional statement is
+#v+
+ if (x != 0)
+ {
+ y = 1.0 / x;
+ if (x > 0) z = log (x);
+ }
+#v-
+ This example illustrates two \var{if} statements where the second
+ \var{if} statement is part of the block of statements that belong to
+ the first.
+
+\sect2{if-else}
+ Another form of \kw{if} statement is the \em{if-else} statement.
+ It follows the syntax:
+\begin{tscreen}
+ if (\em{integer-expression}) \em{statement-or-block-1}
+ else \em{statement-or-block-2}
+ \em{next-statement}
+\end{tscreen}
+ Here, if \em{expression} returns non-zero,
+ \em{statement-or-block-1} will get executed and control will pass
+ on to \em{next-statement}. However, if \em{expression} returns zero,
+ \em{statement-or-block-2} will get executed before continuing with
+ \em{next-statement}. A simple example of this form is
+#v+
+ if (x > 0) z = log (x); else error ("x must be positive");
+#v-
+ Consider the more complex example:
+#v+
+ if (city == "Boston")
+ if (street == "Beacon") found = 1;
+ else if (city == "Madrid")
+ if (street == "Calle Mayor") found = 1;
+ else found = 0;
+#v-
+ This example illustrates a problem that beginners have with
+ \em{if-else} statements. The grammar presented above shows that
+ the this example is equivalent to
+#v+
+ if (city == "Boston")
+ {
+ if (street == "Beacon") found = 1;
+ else if (city == "Madrid")
+ {
+ if (street == "Calle Mayor") found = 1;
+ else found = 0;
+ }
+ }
+#v-
+ It is important to understand the grammar and not be seduced by the
+ indentation!
+
+\sect2{!if}
+
+ One often encounters \kw{if} statements similar to
+\begin{tscreen}
+ if (\em{integer-expression} == 0) \em{statement-or-block}
+\end{tscreen}
+ or equivalently,
+\begin{tscreen}
+ if (not(\em{integer-expression})) \em{statement-or-block}
+\end{tscreen}
+ The \kw{!if} statement was added to the language to simplify the
+ handling of such statements. It obeys the syntax
+\begin{tscreen}
+ !if (\em{integer-expression}) \em{statement-or-block}
+\end{tscreen}
+ and is functionally equivalent to
+\begin{tscreen}
+ if (not (\em{expression})) \em{statement-or-block}
+\end{tscreen}
+
+\sect2{orelse, andelse}
+
+ These constructs were discussed earlier. The syntax for the
+ \var{orelse} statement is:
+\begin{tscreen}
+ orelse {\em{integer-expression-1}} ... {\em{integer-expression-n}}
+\end{tscreen}
+ This causes each of the blocks to be executed in turn until one of
+ them returns a non-zero integer value. The result of this statement
+ is the integer value returned by the last block executed. For
+ example,
+#v+
+ orelse { 0 } { 6 } { 2 } { 3 }
+#v-
+ returns \var{6} since the second block is the first to return a
+ non-zero result. The last two block will not get executed.
+
+ The syntax for the \var{andelse} statement is:
+\begin{tscreen}
+ andelse {\em{integer-expression-1}} ... {\em{integer-expression-n}}
+\end{tscreen}
+ Each of the blocks will be executed in turn until one of
+ them returns a zero value. The result of this statement is the
+ integer value returned by the last block executed. For example,
+#v+
+ andelse { 6 } { 2 } { 0 } { 4 }
+#v-
+ returns \var{0} since the third block will be the last to execute.
+
+\sect2{switch}
+ The switch statement deviates the most from its C counterpart. The
+ syntax is:
+#v+
+ switch (x)
+ { ... : ...}
+ .
+ .
+ { ... : ...}
+#v-
+ The `\var{:}' operator is a special symbol which means to test
+ the top item on the stack, and if it is non-zero, the rest of the block
+ will get executed and control will pass out of the switch statement.
+ Otherwise, the execution of the block will be terminated and the process
+ will be repeated for the next block. If a block contains no
+ \var{:} operator, the entire block is executed and control will
+ pass onto the next statement following the \kw{switch} statement.
+ Such a block is known as the \em{default} case.
+
+ As a simple example, consider the following:
+#v+
+ switch (x)
+ { x == 1 : message("Number is one.");}
+ { x == 2 : message("Number is two.");}
+ { x == 3 : message("Number is three.");}
+ { x == 4 : message("Number is four.");}
+ { x == 5 : message("Number is five.");}
+ { message ("Number is greater than five.");}
+#v-
+ Suppose \var{x} has an integer value of \exmp{3}. The first two
+ blocks will terminate at the `\var{:}' character because each of the
+ comparisons with \var{x} will produce zero. However, the third
+ block will execute to completion. Similarly, if \var{x} is
+ \exmp{7}, only the last block will execute in full.
+
+ A more familiar way to write the previous example used the
+ \kw{case} keyword:
+#v+
+ switch (x)
+ { case 1 : print("Number is one.");}
+ { case 2 : print("Number is two.");}
+ { case 3 : print("Number is three.");}
+ { case 4 : print("Number is four.");}
+ { case 5 : print("Number is five.");}
+ { print ("Number is greater than five.");}
+#v-
+ The \var{case} keyword is a more useful comparison operator because
+ it can perform a comparison between different data types while
+ using \var{==} may result in a type-mismatch error. For example,
+#v+
+ switch (x)
+ { (x == 1) or (x == "one") : print("Number is one.");}
+ { (x == 2) or (x == "two") : print("Number is two.");}
+ { (x == 3) or (x == "three") : print("Number is three.");}
+ { (x == 4) or (x == "four") : print("Number is four.");}
+ { (x == 5) or (x == "five") : print("Number is five.");}
+ { print ("Number is greater than five.");}
+#v-
+ will fail because the \var{==} operation is not defined between
+ strings and integers. The correct way to write this to use the
+ \var{case} keyword:
+#v+
+ switch (x)
+ { case 1 or case "one" : print("Number is one.");}
+ { case 2 or case "two" : print("Number is two.");}
+ { case 3 or case "three" : print("Number is three.");}
+ { case 4 or case "four" : print("Number is four.");}
+ { case 5 or case "five" : print("Number is five.");}
+ { print ("Number is greater than five.");}
+#v-
+
+#%}}}
+
+\sect1{Looping Forms} #%{{{
+
+\sect2{while}
+ The \kw{while} statement follows the syntax
+\begin{tscreen}
+ while (\em{integer-expression}) \em{statement-or-block}
+ \em{next-statement}
+\end{tscreen}
+ It simply causes \em{statement-or-block} to get executed as long as
+ \em{integer-expression} evaluates to a non-zero result. For
+ example,
+#v+
+ i = 10;
+ while (i)
+ {
+ i--;
+ newline ();
+ }
+#v-
+ will cause the \var{newline} function to get called 10 times.
+ However,
+#v+
+ i = -10;
+ while (i)
+ {
+ i--;
+ newline ();
+ }
+#v-
+ would loop forever (or until \var{i} wraps from the most negative
+ integer value to the most positive and then decrements to zero).
+
+
+ If you are a C programmer, do not let the syntax of the language
+ seduce you into writing this example as you would in C:
+#v+
+ i = 10;
+ while (i--) newline ();
+#v-
+ The fact is that expressions such as \var{i--} do not return a
+ value in \slang as they do in C. If you must write this way, use
+ the comma operator as in
+#v+
+ i = 10;
+ while (i, i--) newline ();
+#v-
+
+\sect2{do...while}
+ The \kw{do...while} statement follows the syntax
+\begin{tscreen}
+ do
+ \em{statement-or-block}
+ while (\em{integer-expression});
+\end{tscreen}
+ The main difference between this statement and the \var{while}
+ statement is that the \kw{do...while} form performs the test
+ involving \em{integer-expression} after each execution
+ of \em{statement-or-block} rather than before. This guarantees that
+ \em{statement-or-block} will get executed at least once.
+
+ A simple example from the \jed editor follows:
+#v+
+ bob (); % Move to beginning of buffer
+ do
+ {
+ indent_line ();
+ }
+ while (down (1));
+#v-
+ This will cause all lines in the buffer to get indented via the
+ \jed intrinsic function \var{indent_line}.
+
+\sect2{for}
+ Perhaps the most complex looping statement is the \kw{for}
+ statement; nevertheless, it is a favorite of many programmers.
+ This statement obeys the syntax
+\begin{tscreen}
+ for (\em{init-expression}; \em{integer-expression}; \em{end-expression})
+ \em{statement-or-block}
+ \em{next-statement}
+\end{tscreen}
+ In addition to \em{statement-or-block}, its specification requires
+ three other expressions. When executed, the \kw{for} statement
+ evaluates \em{init-expression}, then it tests
+ \em{integer-expression}. If \em{integer-expression} returns zero,
+ control passes to \em{next-statement}. Otherwise, it executes
+ \em{statement-or-block} as long as \em{integer-expression}
+ evaluates to a non-zero result. After every execution of
+ \em{statement-or-block}, \em{end-expression} will get evaluated.
+
+ This statement is \em{almost} equivalent to
+\begin{tscreen}
+ \em{init-expression};
+ while (\em{integer-expression})
+ {
+ \em{statement-or-block}
+ \em{end-expression};
+ }
+\end{tscreen}
+ The reason that they are not fully equivalent involves what happens
+ when \em{statement-or-block} contains a \kw{continue} statement.
+
+ Despite the apparent complexity of the \kw{for} statement, it is
+ very easy to use. As an example, consider
+#v+
+ s = 0;
+ for (i = 1; i <= 10; i++) s += i;
+#v-
+ which computes the sum of the first 10 integers.
+
+\sect2{loop}
+ The \kw{loop} statement simply executes a block of code a fixed
+ number of times. It follows the syntax
+\begin{tscreen}
+ loop (\em{integer-expression}) \em{statement-or-block}
+ \em{next-statement}
+\end{tscreen}
+ If the \em{integer-expression} evaluates to a positive integer,
+ \em{statement-or-block} will get executed that many times.
+ Otherwise, control will pass to \em{next-statement}.
+
+ For example,
+#v+
+ loop (10) newline ();
+#v-
+ will cause the function \var{newline} to get called 10 times.
+
+\sect2{_for}
+ Like \kw{loop}, the \kw{_for} statement simply executes a block of
+ code a fixed number times. Unlike the \kw{loop} statement, the
+ \kw{_for} loop is useful in situations where the loop index is
+ needed. It obeys the syntax
+\begin{tscreen}
+ _for (\em{first-value}, \em{last-value}, \em{increment})
+ \em{block}
+ \em{next-statement}
+\end{tscreen}
+ Each time through the loop, the current value of the loop index is
+ pushed onto the stack. The first time through, the loop index
+ will have the value of \em{first-value}. The second time its value
+ will be \em{first-value} + \em{increment}, and so on. The loop
+ will terminate when the value of the loop index exceeds
+ \em{last-value}. The current implementation requires the control
+ parameters \em{first-value}, \em{last-value}, and \em{increment} to
+ be integered valued expressions.
+
+ For example, it may be used to compute the sum of the first ten
+ integers:
+#v+
+ s = 0;
+ _for (1, 10, 1)
+ {
+ i = ();
+ s += i;
+ }
+#v-
+
+ The execution speed of the \kw{_for} loop is more than twice as fast as
+ the more powerful \kw{for} loop making it a better choice for many
+ situations.
+
+\sect2{forever}
+ The \kw{forever} statement is similar to the \kw{loop} statement
+ except that it loops forever, or until a \kw{break} or a
+ \kw{return} statement is executed. It obeys the syntax
+\begin{tscreen}
+ forever \em{statement-or-block}
+\end{tscreen}
+ A trivial example of this statement is
+#v+
+ n = 10;
+ forever
+ {
+ if (n == 0) break;
+ newline ();
+ n--;
+ }
+#v-
+
+\sect2{foreach}
+ The \kw{foreach} statement is used to loop over one or more
+ statements for every element in a container object. A container
+ object is a data type that consists of other types. Examples
+ include both ordinary and associative arrays, structures, and
+ strings. Every time through the loop the current member of the
+ object is pushed onto the stack.
+
+ The simple type of \kw{foreach} statement obeys the syntax
+\begin{tscreen}
+ foreach (\em{container-object}) \em{statement-or-block}
+\end{tscreen}
+ Here \em{container-object} can be an expression that returns a
+ container object. A simple example is
+#v+
+ foreach (["apple", "peach", "pear"])
+ {
+ fruit = ();
+ process_fruit (fruit);
+ }
+#v-
+ This example shows that if the container object is an array, then
+ successive elements of the array are pushed onto the stack prior to
+ each execution cycle. If the container object is a string, then
+ successive characters of the string are pushed onto the stack.
+
+ What actually gets pushed onto the stack may be controlled via the
+ \kw{using} form of the \kw{foreach} statement. This more complex
+ type of \kw{foreach} statement follows the syntax
+\begin{tscreen}
+ foreach ( \em{container-object} ) using ( \em{control-list} )
+ \em{statement-or-block}
+\end{tscreen}
+ The allowed values of \em{control-list} will depend upon the type
+ of container object. For associative arrays (\var{Assoc_Type}),
+ \em{control-list} specified whether \em{keys}, \em{values}, or both
+ are pushed onto the stack. For example,
+#v+
+ foreach (a) using ("keys")
+ {
+ k = ();
+ .
+ .
+ }
+#v-
+ results in the keys of the associative array \var{a} being pushed
+ on the list. However,
+#v+
+ foreach (a) using ("values")
+ {
+ v = ();
+ .
+ .
+ }
+#v-
+ will cause the values to be used, and
+#v+
+ foreach (a) using ("keys", "values")
+ {
+ (k,v) = ();
+ .
+ .
+ }
+#v-
+ will use both the keys and values of the array.
+
+ Similarly, for linked-lists of structures, one may walk the list via
+ code like
+#v+
+ foreach (linked_list) using ("next")
+ {
+ s = ();
+ .
+ .
+ }
+#v-
+ This \kw{foreach} statement is equivalent
+#v+
+ s = linked_list;
+ while (s != NULL)
+ {
+ .
+ .
+ s = s.next;
+ }
+#v-
+ Consult the type-specific documentation for a discussion of the
+ \kw{using} control words, if any, appropriate for a given type.
+
+\sect{break, return, continue}
+
+ \slang also includes the non-local transfer functions \var{return}, \var{break},
+ and \var{continue}. The \var{return} statement causes control to return to the
+ calling function while the \var{break} and \var{continue} statements are used in
+ the context of loop structures. Consider:
+#v+
+ define fun ()
+ {
+ forever
+ {
+ s1;
+ s2;
+ ..
+ if (condition_1) break;
+ if (condition_2) return;
+ if (condition_3) continue;
+ ..
+ s3;
+ }
+ s4;
+ ..
+ }
+#v-
+ Here, a function \var{fun} has been defined that contains a \var{forever}
+ loop consisting of statements \var{s1}, \var{s2},\ldots,\var{s3}, and
+ three \var{if} statements. As long as the expressions \var{condition_1},
+ \var{condition_2}, and \var{condition_3} evaluate to zero, the statements
+ \var{s1}, \var{s2},\ldots,\var{s3} will be repeatedly executed. However,
+ if \var{condition_1} returns a non-zero value, the \var{break} statement
+ will get executed, and control will pass out of the \var{forever} loop to
+ the statement immediately following the loop which in this case is
+ \var{s4}. Similarly, if \var{condition_2} returns a non-zero number,
+ the \var{return} statement will cause control to pass back to the
+ caller of \var{fun}. Finally, the \var{continue} statement will
+ cause control to pass back to the start of the loop, skipping the
+ statement \var{s3} altogether.
+
+
+#%}}}
+
+#%}}}
+
+#%}}}
+
+\chapter{Functions} #%{{{
+
+ A function may be thought of as a group of statements that work
+ together to perform a computation. While there are no imposed
+ limits upon the number statements that may occur within a function,
+ it is considered poor programming practice if a function contains
+ many statements. This notion stems from the belief that a function
+ should have a simple, well defined purpose.
+
+\sect{Declaring Functions} #%{{{
+
+ Like variables, functions must be declared before they can be used. The
+ \kw{define} keyword is used for this purpose. For example,
+#v+
+ define factorial ();
+#v-
+ is sufficient to declare a function named \var{factorial}. Unlike
+ the \var{variable} keyword used for declaring variables, the
+ \var{define} keyword does not accept a list of names.
+
+ Usually, the above form is used only for recursive functions. In
+ most cases, the function name is almost always followed by a
+ parameter list and the body of the function:
+\begin{tscreen}
+ define \em{function-name} (\em{parameter-list})
+ {
+ \em{statement-list}
+ }
+\end{tscreen}
+ The \em{function-name} is an identifier and must conform to the
+ naming scheme for identifiers discussed in chapter ???.
+ The \em{parameter-list} is a comma-separated list of variable names
+ that represent parameters passed to the function, and
+ may be empty if no parameters are to be passed.
+ The body of the function is enclosed in braces and consists of zero
+ or more statements (\em{statement-list}).
+
+ The variables in the \em{parameter-list} are implicitly declared,
+ thus, there is no need to declare them via a variable declaration
+ statement. In fact any attempt to do so will result in a syntax
+ error.
+
+#%}}}
+
+\sect{Parameter Passing Mechanism} #%{{{
+
+ Parameters to a function are always passed by value and never by
+ reference. To see what this means, consider
+#v+
+ define add_10 (a)
+ {
+ a = a + 10;
+ }
+ variable b = 0;
+ add_10 (b);
+#v-
+ Here a function \var{add_10} has been defined, which when executed,
+ adds \exmp{10} to its parameter. A variable \var{b} has also been
+ declared and initialized to zero before it is passed to
+ \var{add_10}. What will be the value of \var{b} after the call to
+ \var{add_10}? If \slang were a language that passed parameters by
+ reference, the value of \var{b} would be changed to
+ \var{10}. However, \slang always passes by value, which means that
+ \var{b} would retain its value of zero after the function call.
+
+ \slang does provide a mechanism for simulating pass by reference
+ via the reference operator. See the next section for more details.
+
+ If a function is called with a parameter in the parameter list
+ omitted, the corresponding variable in the function will be set to
+ \var{NULL}. To make this clear, consider the function
+#v+
+ define add_two_numbers (a, b)
+ {
+ if (a == NULL) a = 0;
+ if (b == NULL) b = 0;
+ return a + b;
+ }
+#v-
+ This function must be called with two parameters. However, we can
+ omit one or both of the parameters by calling it in one of the
+ following ways:
+#v+
+ variable s = add_two_numbers (2,3);
+ variable s = add_two_numbers (2,);
+ variable s = add_two_numbers (,3);
+ variable s = add_two_numbers (,);
+#v-
+ The first example calls the function using both parameters;
+ however, at least one of the parameters was omitted in the other
+ examples. The interpreter will implicitly convert the last three
+ examples to
+#v+
+ variable s = add_two_numbers (2, NULL);
+ variable s = add_two_numbers (NULL, 3);
+ variable s = add_two_numbers (NULL, NULL);
+#v-
+ It is important to note that this mechanism is available only for
+ function calls that specify more than one parameter. That is,
+#v+
+ variable s = add_10 ();
+#v-
+ is \em{not} equivalent to \exmp{add_10(NULL)}. The reason for this
+ is simple: the parser can only tell whether or not \var{NULL} should
+ be substituted by looking at the position of the comma character in
+ the parameter list, and only function calls that indicate more than
+ one parameter will use a comma. A mechanism for handling single
+ parameter function calls is described in the next section.
+
+#%}}}
+
+\sect{Referencing Variables} #%{{{
+
+ One can achieve the effect of passing by reference by using the
+ reference (\var{&}) and dereference (\var{@}) operators. Consider
+ again the \var{add_10} function presented in the previous section.
+ This time we write it as
+#v+
+ define add_10 (a)
+ {
+ @a = @a + 10;
+ }
+ variable b = 0;
+ add_10 (&b);
+#v-
+ The expression \var{&b} creates a \em{reference} to the variable
+ \var{b} and it is the reference that gets passed to \var{add_10}.
+ When the function \var{add_10} is called, the value of \var{a} will
+ be a reference to \var{b}. It is only by \em{dereferencing} this
+ value that \var{b} can be accessed and changed. So, the statement
+ \exmp{@a=@a+10;} should be read `add \exmp{10}' to the value of the
+ object that \var{a} references and assign the result to the object
+ that \var{a} references.
+
+ The reader familiar with C will note the similarity between
+ \em{references} in \slang and \em{pointers} in C.
+
+ One of the main purposes for references is that this mechanism
+ allows reference to functions to be passed to other functions. As
+ a simple example from elementary calculus, consider the following
+ function which returns an approximation to the derivative of another
+ function at a specified point:
+#v+
+ define derivative (f, x)
+ {
+ variable h = 1e-6;
+ return ((@f)(x+h) - (@f)(x)) / h;
+ }
+#v-
+ It can be used to differentiate the function
+#v+
+ define x_squared (x)
+ {
+ return x^2;
+ }
+#v-
+ at the point \exmp{x = 3} via the expression
+ \exmp{derivative(&x_squared,3)}.
+
+
+#%}}}
+
+\sect{Functions with a Variable Number of Arguments} #%{{{
+
+ \slang functions may be defined to take a variable number of
+ arguments. The reason for this is that the calling routine pushes
+ the arguments onto the stack before making a function call, and it
+ is up to the called function to pop the values off the stack and
+ make assignments to the variables in the parameter list. These
+ details are, for the most part, hidden from the programmer.
+ However, they are important when a variable number of arguments are
+ passed.
+
+ Consider the \var{add_10} example presented earlier. This time it
+ is written
+#v+
+ define add_10 ()
+ {
+ variable x;
+ x = ();
+ return x + 10;
+ }
+ variable s = add_10 (12); % ==> s = 22;
+#v-
+ For the uninitiated, this example looks as if it
+ is destined for disaster. The \var{add_10} function looks like it
+ accepts zero arguments, yet it was called with a single argument.
+ On top of that, the assignment to \var{x} looks strange. The truth
+ is, the code presented in this example makes perfect sense, once you
+ realize what is happening.
+
+ First, consider what happened when \var{add_10} is called with the
+ the parameter \exmp{12}. Internally, \exmp{12} is
+ pushed onto the stack and then the function called. Now,
+ consider the function itself. \var{x} is a variable local to the
+ function. The strange looking assignment `\exmp{x=()}' simply
+ takes whatever is on the stack and assigns it to \var{x}. In
+ other words, after this statement, the value of \var{x} will be
+ \exmp{12}, since \exmp{12} will be at the top of the stack.
+
+ A generic function of the form
+#v+
+ define function_name (x, y, ..., z)
+ {
+ .
+ .
+ }
+#v-
+ is internally transformed by the interpreter to
+#v+
+ define function_name ()
+ {
+ variable x, y, ..., z;
+ z = ();
+ .
+ .
+ y = ();
+ x = ();
+ .
+ .
+ }
+#v-
+ before further parsing. (The \var{add_10} function, as defined above, is
+ already in this form.) With this knowledge in hand, one can write a
+ function that accepts a variable number of arguments. Consider the
+ function:
+#v+
+ define average_n (n)
+ {
+ variable x, y;
+ variable s;
+
+ if (n == 1)
+ {
+ x = ();
+ s = x;
+ }
+ else if (n == 2)
+ {
+ y = ();
+ x = ();
+ s = x + y;
+ }
+ else error ("average_n: only one or two values supported");
+
+ return s / n;
+ }
+ variable ave1 = average_n (3.0, 1); % ==> 3.0
+ variable ave2 = average_n (3.0, 5.0, 2); % ==> 4.0
+#v-
+ Here, the last argument passed to \var{average_n} is an integer
+ reflecting the number of quantities to be averaged. Although this
+ example works fine, its principal limitation is obvious: it only
+ supports one or two values. Extending it to three or more values
+ by adding more \exmp{else if} constructs is rather straightforward but
+ hardly worth the effort. There must be a better way, and there is:
+#v+
+ define average_n (n)
+ {
+ variable s, x;
+ s = 0;
+ loop (n)
+ {
+ x = (); % get next value from stack
+ s += x;
+ }
+ return s / n;
+ }
+#v-
+ The principal limitation of this approach is that one must still
+ pass an integer that specifies how many values are to be averaged.
+
+ Fortunately, a special variable exists that is local to every function
+ and contains the number of values that were passed to the function.
+ That variable has the name \var{_NARGS} and may be used as follows:
+#v+
+ define average_n ()
+ {
+ variable x, s = 0;
+
+ if (_NARGS == 0) error ("Usage: ave = average_n (x, ...);");
+
+ loop (_NARGS)
+ {
+ x = ();
+ s += x;
+ }
+ return s / _NARGS;
+ }
+#v-
+ Here, if no arguments are passed to the function, a simple message
+ that indicates how it is to be used is printed out.
+
+
+#%}}}
+
+
+\sect{Returning Values}
+
+ As stated earlier, the usual way to return values from a function
+ is via the \kw{return} statement. This statement has the
+ simple syntax
+\begin{tscreen}
+ return \em{expression-list} ;
+\end{tscreen}
+ where \em{expression-list} is a comma separated list of expressions.
+ If the function does not return any values, the expression list
+ will be empty. As an example of a function that can return
+ multiple values, consider
+#v+
+ define sum_and_diff (x, y)
+ {
+ variable sum, diff;
+
+ sum = x + y; diff = x - y;
+ return sum, diff;
+ }
+#v-
+ which is a function returning two values.
+
+ It is extremely important to note that \em{the calling routine must
+ explicitly handle all values returned by a function}. Although
+ some languages such as C do not have this restriction, \slang does
+ and it is a direct result of a \slang function's ability to return
+ many values and accept a variable number of parameters. Examples
+ of properly handling the above function include
+#v+
+ variable s, d;
+ (s, d) = sum_and_diff (5, 4); % ignore neither
+ (s,) = sum_and_diff (5, 4); % ignore diff
+ (,) = sum_and_diff (5, 4); % ignore both sum and diff
+#v-
+ See the section below on assignment statements for more information
+ about this important point.
+
+\sect{Multiple Assignment Statement} #%{{{
+
+ \slang functions can return more than one value, e.g.,
+#v+
+ define sum_and_diff (x, y)
+ {
+ return x + y, x - y;
+ }
+#v-
+ returns two values. It accomplishes this by placing both values on
+ the stack before returning. If you understand how \slang functions
+ handle a variable number of parameters (section ???), then it
+ should be rather obvious that one assigns such values to variables.
+ One way is to use, e.g.,
+#v+
+ sum_and_diff (9, 4);
+ d = ();
+ s = ();
+#v-
+
+ However, the most convenient way to accomplish this is to use a
+ \em{multiple assignment statement} such as
+#v+
+ (s, d) = sum_and_diff (9, 4);
+#v-
+ The most general form of the multiple assignment statement is
+#v+
+ ( var_1, var_2, ..., var_n ) = expression;
+#v-
+ In fact, internally the interpreter transforms this statement into
+ the form
+#v+
+ expression; var_n = (); ... var_2 = (); var_1 = ();
+#v-
+ for further processing.
+
+ If you do not care about one of return values, simply omit the
+ variable name from the list. For example,
+#v+
+ (s, ) = sum_and_diff (9, 4);
+#v-
+ assigns the sum of \exmp{9} and \exmp{4} to \var{s} and the
+ difference (\exmp{9-4}) will be removed from the stack.
+
+ As another example, the \jed editor provides a function called
+ \var{down} that takes an integer argument and returns an integer.
+ It is used to move the current editing position down the number of
+ lines specified by the argument passed to it. It returns the number
+ of lines it successfully moved the editing position. Often one does
+ not care about the return value from this function. Although it is
+ always possible to handle the return value via
+#v+
+ variable dummy = down (10);
+#v-
+ it is more convenient to use a multiple assignment expression and
+ omit the variable name, e.g.,
+#v+
+ () = down (10);
+#v-
+
+ Some functions return a \em{variable number} of values instead of a
+ \em{fixed number}. Usually, the value at the top of the stack will
+ indicate the actual number of return values. For such functions,
+ the multiple assignment statement cannot directly be used. To see
+ how such functions can be dealt with, consider the following
+ function:
+#v+
+ define read_line (fp)
+ {
+ variable line;
+ if (-1 == fgets (&line, fp))
+ return -1;
+ return (line, 0);
+ }
+#v-
+ This function returns either one or two values, depending upon the
+ return value of \var{fgets}. Such a function may be handled as in
+ the following example:
+#v+
+ status = read_line (fp);
+ if (status != -1)
+ {
+ s = ();
+ .
+ .
+ }
+#v-
+ In this example, the \em{last} value returned by \var{read_line} is
+ assigned to \var{status} and then tested. If it is non-zero, the
+ second return value is assigned to \var{s}. In particular note the
+ empty set of parenthesis in the assignment to \var{s}. This simply
+ indicates that whatever is on the top of the stack when the
+ statement is executed will be assigned to \var{s}.
+
+ Before leaving this section it is important to reiterate the fact
+ that if a function returns a value, the caller must deal with that
+ return value. Otherwise, the value will continue to live onto the
+ stack and may eventually lead to a stack overflow error.
+ Failing to handle the return value of a function is the
+ most common mistake that inexperienced \slang programmers make.
+ For example, the \var{fflush} function returns a value that many C
+ programmer's never check. Instead of writing
+#v+
+ fflush (fp);
+#v-
+ as one could in C, a \slang programmer should write
+#v+
+ () = fflush (fp);
+#v-
+ in \slang. (Many good C programmer's write \exmp{(void)fflush(fp)}
+ to indicate that the return value is being ignored).
+
+#%}}}
+
+\sect{Exit-Blocks}
+
+ An \em{exit-block} is a set of statements that get executed when a
+ functions returns. They are very useful for cleaning up when a
+ function returns via an explicit call to \var{return} from deep
+ within a function.
+
+ An exit-block is created by using the \kw{EXIT_BLOCK} keyword
+ according to the syntax
+\begin{tscreen}
+ EXIT_BLOCK { \em{statement-list} }
+\end{tscreen}
+ where \em{statement-list} represents the list of statements that
+ comprise the exit-block. The following example illustrates the use
+ of an exit-block:
+#v+
+ define simple_demo ()
+ {
+ variable n = 0;
+
+ EXIT_BLOCK { message ("Exit block called."); }
+
+ forever
+ {
+ if (n == 10) return;
+ n++;
+ }
+ }
+#v-
+ Here, the function contains an exit-block and a \var{forever} loop.
+ The loop will terminate via the \kw{return} statement when \var{n}
+ is 10. Before it returns, the exit-block will get executed.
+
+ A function can contain multiple exit-blocks, but only the last
+ one encountered during execution will actually get executed. For
+ example,
+#v+
+ define simple_demo (n)
+ {
+ EXIT_BLOCK { return 1; }
+
+ if (n != 1)
+ {
+ EXIT_BLOCK { return 2; }
+ }
+ return;
+ }
+#v-
+ If \var{1} is passed to this function, the first exit-block will
+ get executed because the second one would not have been encountered
+ during the execution. However, if some other value is passed, the
+ second exit-block would get executed. This example also
+ illustrates that it is possible to explicitly return from an
+ exit-block, although nested exit-blocks are illegal.
+
+#%}}}
+
+\chapter{Name Spaces} #%{{{
+
+ By default, all global variables and functions are defined in the
+ global namespace. In addition to the global namespace, every
+ compilation unit (e.g., a file containing \slang code) has an
+ anonymous namespace. Objects may be defined in the anonymous
+ namespace via the \var{static} declaration keyword. For example,
+#v+
+ static variable x;
+ static define hello () { message ("hello"); }
+#v-
+ defines a variable \var{x} and a function \var{hello} in the
+ anonymous namespace. This is useful when one wants to define
+ functions and variables that are only to be used within the file, or
+ more precisely the compilation unit, that defines them.
+
+ The \var{implements} function may be used to give the anonymous
+ namespace a name to allow access to its objects from outside the
+ compilation unit that defines them. For example,
+#v+
+ implements ("foo");
+ static variable x;
+#v-
+ allows the variable \var{x} to be accessed via \var{foo->x}, e.g.,
+#v+
+ if (foo->x == 1) foo->x = 2;
+#v-
+
+ The \var{implements} function does more than simply giving the
+ anonymous namespace a name. It also changes the default variable
+ and function declaration mode from \var{public} to \var{static}.
+ That is,
+#v+
+ implements ("foo");
+ variable x;
+#v-
+ and
+#v+
+ implements ("foo");
+ static variable x;
+#v-
+ are equivalent. Then to create a public object within the
+ namespace, one must explicitly use the \var{public} keyword.
+
+ Finally, the \var{private} keyword may be used to create an object
+ that is truly private within the compilation unit. For example,
+#v+
+ implements ("foo");
+ variable x;
+ private variable y;
+#v-
+ allows \var{x} to be accessed from outside the namespace via
+ \var{foo->x}, however \var{y} cannot be accessed.
+
+#%}}}
+
+\chapter{Arrays} #%{{{
+
+ An array is a container object that can contain many values of one
+ data type. Arrays are very useful objects and are indispensable
+ for certain types of programming. The purpose of this chapter is
+ to describe how arrays are defined and used in the \slang language.
+
+\sect{Creating Arrays} #%{{{
+
+ The \slang language supports multi-dimensional arrays of all data
+ types. Since the \var{Array_Type} is a data type, one can even
+ have arrays of arrays. To create a multi-dimensional array of
+ \em{SomeType} use the syntax
+#v+
+ SomeType [dim0, dim1, ..., dimN]
+#v-
+ Here \em{dim0}, \em{dim1}, ... \em{dimN} specify the size of
+ the individual dimensions of the array. The current implementation
+ permits arrays consist of up to \var{7} dimensions. When a
+ numeric array is created, all its elements are initialized to zero.
+ The initialization of other array types depend upon the data type,
+ e.g., \var{String_Type} and \var{Struct_Type} arrays are
+ initialized to \var{NULL}.
+
+ As a concrete example, consider
+#v+
+ a = Integer_Type [10];
+#v-
+ which creates a one-dimensional array of \exmp{10} integers and
+ assigns it to \var{a}.
+ Similarly,
+#v+
+ b = Double_Type [10, 3];
+#v-
+ creates a \var{30} element array of double precision numbers
+ arranged in \var{10} rows and \var{3} columns, and assigns it to
+ \var{b}.
+
+\sect1{Range Arrays}
+
+ There is a more convenient syntax for creating and initializing a
+ 1-d arrays. For example, to create an array of ten
+ integers whose elements run from \exmp{1} through \exmp{10}, one
+ may simply use:
+#v+
+ a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+#v-
+ Similarly,
+#v+
+ b = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0];
+#v-
+ specifies an array of ten doubles.
+
+ An even more compact way of specifying a numeric array is to use a
+ \em{range-array}. For example,
+#v+
+ a = [0:9];
+#v-
+ specifies an array of 10 integers whose elements range from \var{0}
+ through \var{9}. The most general form of a range array is
+#v+
+ [first-value : last-value : increment]
+#v-
+ where the \em{increment} is optional and defaults to \exmp{1}. This
+ creates an array whose first element is \em{first-value} and whose
+ successive values differ by \em{increment}. \em{last-value} sets
+ an upper limit upon the last value of the array as described below.
+
+ If the range array \var{[a:b:c]} is integer valued, then the
+ interval specified by \var{a} and \var{b} is closed. That is, the
+ kth element of the array \math{x_k} is given by \math{x_k=a+ck} and
+ must satisfy \math{a<=x_k<=b}. Hence, the number of elements in an
+ integer range array is given by the expression \math{1 + (b-a)/c}.
+
+ The situation is somewhat more complicated for floating point range
+ arrays. The interval specified by a floating point range array
+ \var{[a:b:c]} is semi-open such that \var{b} is not contained in
+ the interval. In particular, the kth element of \var{[a:b:c]} is
+ given by \math{x_k=a+kc} such that \math{a<=x_k<b} when
+ \math{c>=0}, and \math{b<x_k<=a} otherwise. The number of elements
+ in the array is one greater than the largest \math{k} that
+ satisfies the open interval constraint.
+
+ Here are a few examples that illustrate the above comments:
+#v+
+ [1:5:1] ==> [1,2,3,4,5]
+ [1.0:5.0:1.0] ==> [1.0, 2.0, 3.0, 4.0]
+ [5:1:-1] ==> [5,4,3,2,1]
+ [5.0:1.0:-1.0] ==> [5.0, 4.0, 3.0, 2.0];
+ [1:1] ==> [1]
+ [1.0:1.0] ==> []
+ [1:-3] ==> []
+#v-
+
+\sect1{Creating arrays via the dereference operator}
+
+ Another way to create an array is apply the dereference operator
+ \var{@} to the \var{DataType_Type} literal \var{Array_Type}. The
+ actual syntax for this operation resembles a function call
+\begin{tscreen}
+ variable a = @Array_Type (\em{data-type}, \em{integer-array});
+\end{tscreen}
+ where \em{data-type} is of type \var{DataType_Type} and
+ \em{integer-array} is a 1-d array of integers that specify the size
+ of each dimension. For example,
+#v+
+ variable a = @Array_Type (Double_Type, [10, 20]);
+#v-
+ will create a \exmp{10} by \var{20} array of doubles and assign it
+ to \var{a}. This method of creating arrays derives its power from
+ the fact that it is more flexible than the methods discussed in this
+ section. We shall encounter it again in section ??? in the context
+ of the \var{array_info} function.
+
+#%}}}
+
+\sect{Reshaping Arrays} #%{{{
+ It is sometimes possible to change the `shape' of an array using
+ the \var{reshape} function. For example, a 1-d 10 element array
+ may be reshaped into a 2-d array consisting of 5 rows and 2
+ columns. The only restriction on the operation is that the arrays
+ must be commensurate. The \var{reshape} function follows the
+ syntax
+\begin{tscreen}
+ reshape (\em{array-name}, \em{integer-array});
+\end{tscreen}
+ where \em{array-name} specifies the array to be reshaped to have
+ the dimensions given by \var{integer-array}, a 1-dimensional array of
+ integers. It is important to note that this does \em{not} create a
+ new array, it simply reshapes the existing array. Thus,
+#v+
+ variable a = Double_Type [100];
+ reshape (a, [10, 10]);
+#v-
+ turns \var{a} into a \exmp{10} by \exmp{10} array.
+
+#%}}}
+
+\sect{Indexing Arrays} #%{{{
+ An individual element of an array may be referred to by its
+ \em{index}. For example, \exmp{a[0]} specifies the zeroth element
+ of the one dimensional array \var{a}, and \exmp{b[3,2]} specifies
+ the element in the third row and second column of the two
+ dimensional array \var{b}. As in C array indices are numbered from
+ \var{0}. Thus if \var{a} is a one-dimensional array of ten
+ integers, the last element of the array is given by \var{a[9]}.
+ Using \var{a[10]} would result in a range error.
+
+ A negative index may be used to index from the end of the array,
+ with \exmp{a[-1]} referring to the last element of \var{a},
+ \exmp{a[-2]} referring to the next to the last element, and so on.
+
+ One may use the indexed value like any other variable. For
+ example, to set the third element of an integer array to \var{6}, use
+#v+
+ a[2] = 6;
+#v-
+ Similarly, that element may be used in an expression, such as
+#v+
+ y = a[2] + 7;
+#v-
+ Unlike other \slang variables which inherit a type upon assignment,
+ array elements already have a type. For example, an attempt to
+ assign a string value to an element of an integer array will result
+ in a type-mismatch error.
+
+ One may use any integer expression to index an array. A simple
+ example that computes the sum of the elements of 10 element 1-d
+ array is
+#v+
+ variable i, s;
+ s = 0;
+ for (i = 0; i < 10; i++) s += a[i];
+#v-
+ However, if the built-in \var{sum} function is available (not all programs
+ using \slang support this), then it should be used to compute the
+ sum of an array, e.g.,
+#v+
+ s = sum(a);
+#v-
+
+ Unlike many other languages, \slang permits arrays to be indexed by
+ other integer arrays. Suppose that \var{a} is a 1-d array of 10
+ doubles. Now consider:
+#v+
+ i = [6:8];
+ b = a[i];
+#v-
+ Here, \var{i} is a 1-dimensional range array of three integers with
+ \exmp{i[0]} equal to \exmp{6}, \exmp{i[1]} equal to \exmp{7},
+ and \exmp{i[2]} equal to \exmp{8}. The statement \var{b = a[i];}
+ will create a 1-d array of three doubles and assign it to \var{b}.
+ The zeroth element of \var{b}, \exmp{b[0]} will be set to the sixth
+ element of \var{a}, or \exmp{a[6]}, and so on. In fact, these two simple
+ statements are equivalent to
+#v+
+ b = Double_Type [3];
+ b[0] = a[6];
+ b[1] = a[7];
+ b[2] = a[8];
+#v-
+ except that using an array of indices is not only much more
+ convenient, but executes much faster.
+
+ More generally, one may use an index array to specify which
+ elements are to participate in a calculation. For example, consider
+#v+
+ a = Double_Type [1000];
+ i = [0:499];
+ j = [500:999];
+ a[i] = -1.0;
+ a[j] = 1.0;
+#v-
+ This creates an array of \exmp{1000} doubles and sets the first
+ \exmp{500} elements to \exmp{-1.0} and the last \exmp{500} to
+ \var{1.0}. Actually, one may do away with the \var{i} and \var{j}
+ variables altogether and use
+#v+
+ a = Double_Type [1000];
+ a [[0:499]] = -1.0;
+ a [[500:999]] = 1.0;
+#v-
+ It is important to understand the syntax used and, in particular,
+ to note that \exmp{a[[0:499]]} is \em{not} the same as
+ \exmp{a[0:499]}. In fact, the latter will generate a syntax error.
+
+ Often, it is convenient to use a \em{rubber} range to specify
+ indices. For example, \exmp{a[[500:]]} specifies all elements of
+ \var{a} whose index is greater than or equal to \var{500}. Similarly,
+ \exmp{a[[:499]]} specifies the first 500 elements of \var{a}.
+ Finally, \exmp{a[[:]]} specifies all the elements of \var{a};
+ however, using \exmp{a[*]} is more convenient.
+
+ One should be careful when using index arrays with negative
+ elements. As pointed out above, a negative index is used to index
+ from the end of the array. That is, \exmp{a[-1]} refers to the
+ last element of \exmp{a}. How should \exmp{a[[[0:-1]]} be
+ interpreted? By itself, \var{[0:-1]} is an empty array; hence, one
+ might expect \exmp{a[[0:-1]]} to refer to no elements. However,
+ when used in an array indexing context, \exmp{[0:-1]} is
+ interpreted as an array indexing the first through the last
+ elements of the array. While this is a very convenient mechanism
+ to specifiy the last 3 elements of an array using
+ \exmp{a[[-3:-1]]}, it is very easy to forget these semantics.
+
+ Now consider a multi-dimensional array. For simplicity, suppose
+ that \var{a} is a \exmp{100} by \exmp{100} array of doubles. Then
+ the expression \var{a[0, *]} specifies all elements in the zeroth
+ row. Similarly, \var{a[*, 7]} specifies all elements in the
+ seventh column. Finally, \var{a[[3:5][6:12]]} specifies the
+ \exmp{3} by \exmp{7} region consisting of rows \exmp{3}, \exmp{4},
+ and \exmp{5}, and columns \exmp{6} through \exmp{12} of \var{a}.
+
+ We conclude this section with a few examples.
+
+ Here is a function that computes the trace (sum of the diagonal
+ elements) of a square 2 dimensional \var{n} by \var{n} array:
+#v+
+ define array_trace (a, n)
+ {
+ variable s = 0, i;
+ for (i = 0; i < n; i++) s += a[i, i];
+ return s;
+ }
+#v-
+ This fragment creates a \exmp{10} by \exmp{10} integer array, sets
+ its diagonal elements to \exmp{5}, and then computes the trace of
+ the array:
+#v+
+ a = Integer_Type [10, 10];
+ for (j = 0; j < 10; j++) a[j, j] = 5;
+ the_trace = array_trace(a, 10);
+#v-
+ We can get rid of the \kw{for} loop as follows:
+#v+
+ j = Integer_Type [10, 2];
+ j[*,0] = [0:9];
+ j[*,1] = [0:9];
+ a[j] = 5;
+#v-
+ Here, the goal was to construct a 2-d array of indices that
+ correspond to the diagonal elements of \var{a}, and then use that
+ array to index \var{a}. To understand how
+ this works, consider the middle statements. They are equivalent
+ to the following \var{for} loops:
+#v+
+ variable i;
+ for (i = 0; i < 10; i++) j[i, 0] = i;
+ for (i = 0; i < 10; i++) j[i, 1] = i;
+#v-
+ Thus, row \var{n} of \var{j} will have the value \exmp{(n,n)},
+ which is precisely what was sought.
+
+ Another example of this technique is the function:
+#v+
+ define unit_matrix (n)
+ {
+ variable a = Integer_Type [n, n];
+ variable j = Integer_Type [n, 2];
+ j[*,0] = [0:n - 1];
+ j[*,1] = [0:n - 1];
+
+ a[j] = 1;
+ return a;
+ }
+#v-
+ This function creates an \var{n} by \var{n} unit matrix,
+ that is a 2-d \var{n} by \var{n} array whose elements are all zero
+ except on the diagonal where they have a value of \exmp{1}.
+
+
+#%}}}
+
+\sect{Arrays and Variables}
+
+ When an array is created and assigned to a variable, the
+ interpreter allocates the proper amount of space for the array,
+ initializes it, and then assigns to the variable a \em{reference}
+ to the array. So, a variable that represents an array has a value
+ that is really a reference to the array. This has several
+ consequences, some good and some bad. It is believed that the
+ advantages of this representation outweigh the disadvantages.
+ First, we shall look at the positive aspects.
+
+ When a variable is passed to a function, it is always the value of
+ the variable that gets passed. Since the value of a variable
+ representing an array is a reference, a reference to the array gets
+ passed. One major advantage of this is rather obvious: it is a
+ fast and efficient way to pass the array. This also has another
+ consequence that is illustrated by the function
+#v+
+ define init_array (a, n)
+ {
+ variable i;
+
+ for (i = 0; i < n; i++) a[i] = some_function (i);
+ }
+#v-
+ where \var{some_function} is a function that generates a scalar
+ value to initialize the \em{ith} element. This function can be
+ used in the following way:
+#v+
+ variable X = Double_Type [100000];
+ init_array (X, 100000);
+#v-
+ Since the array is passed to the function by reference, there is no
+ need to make a separate copy of the \var{100000} element array. As
+ pointed out above, this saves both execution time and memory. The
+ other salient feature to note is that any changes made to the
+ elements of the array within the function will be manifested in the
+ array outside the function. Of course, in this case, this is a
+ desirable side-effect.
+
+ To see the downside of this representation, consider:
+#v+
+ variable a, b;
+ a = Double_Type [10];
+ b = a;
+ a[0] = 7;
+#v-
+ What will be the value of \exmp{b[0]}? Since the value of \var{a}
+ is really a reference to the array of ten doubles, and that
+ reference was assigned to \var{b}, \var{b} also refers to the same
+ array. Thus any changes made to the elements of \var{a}, will also
+ be made implicitly to \var{b}.
+
+ This begs the question: If the assignment of one variable which
+ represents an array, to another variable results in the assignment
+ of a reference to the array, then how does one make separate copies
+ of the array? There are several answers including using an index
+ array, e.g., \exmp{b = a[*]}; however, the most natural method is
+ to use the dereference operator:
+#v+
+ variable a, b;
+ a = Double_Type [10];
+ b = @a;
+ a[0] = 7;
+#v-
+ In this example, a separate copy of \var{a} will be created and
+ assigned to \var{b}. It is very important to note that \slang
+ never implicitly dereferences an object. So, one must explicitly use
+ the dereference operator. This means that the elements of a
+ dereferenced array are not themselves dereferenced. For example,
+ consider dereferencing an array of arrays, e.g.,
+#v+
+ variable a, b;
+ a = Array_Type [2];
+ a[0] = Double_Type [10];
+ a[1] = Double_Type [10];
+ b = @a;
+#v-
+ In this example, \exmp{b[0]} will be a reference to the array that
+ \exmp{a[0]} references because \exmp{a[0]} was not explicitly
+ dereferenced.
+
+\sect{Using Arrays in Computations} #%{{{
+
+ Many functions and operations work transparently with arrays.
+ For example, if \var{a} and \var{b} are arrays, then the sum
+ \exmp{a + b} is an array whose elements are formed from the sum of
+ the corresponding elements of \var{a} and \var{b}. A similar
+ statement holds for all other binary and unary operations.
+
+ Let's consider a simple example. Suppose, that we wish to solve a
+ set of \var{n} quadratic equations whose coefficients are given by
+ the 1-d arrays \var{a}, \var{b}, and \var{c}. In general, the
+ solution of a quadratic equation will be two complex numbers. For
+ simplicity, suppose that all we really want is to know what subset of
+ the coefficients, \var{a}, \var{b}, \var{c}, correspond to
+ real-valued solutions. In terms of \var{for} loops, we can write:
+#v+
+ variable i, d, index_array;
+ index_array = Integer_Type [n];
+ for (i = 0; i < n; i++)
+ {
+ d = b[i]^2 - 4 * a[i] * c[i];
+ index_array [i] = (d >= 0.0);
+ }
+#v-
+ In this example, the array \var{index_array} will contain a
+ non-zero value if the corresponding set of coefficients has a
+ real-valued solution. This code may be written much more compactly
+ and with more clarity as follows:
+#v+
+ variable index_array = ((b^2 - 4 * a * c) >= 0.0);
+#v-
+
+ \slang has a powerful built-in function called \var{where}. This
+ function takes an array of integers and returns a 2-d array of
+ indices that correspond to where the elements of the input array
+ are non-zero. This simple operation is extremely useful. For
+ example, suppose \var{a} is a 1-d array of \var{n} doubles, and it
+ is desired to set to zero all elements of the array whose value is
+ less than zero. One way is to use a \var{for} loop:
+#v+
+ for (i = 0; i < n; i++)
+ if (a[i] < 0.0) a[i] = 0.0;
+#v-
+ If \var{n} is a large number, this statement can take some time to
+ execute. The optimal way to achieve the same result is to use the
+ \var{where} function:
+#v+
+ a[where (a < 0.0)] = 0;
+#v-
+ Here, the expression \exmp{(a < 0.0)} returns an array whose
+ dimensions are the same size as \var{a} but whose elements are
+ either \exmp{1} or \exmp{0}, according to whether or not the
+ corresponding element of \var{a} is less than zero. This array of
+ zeros and ones is then passed to \var{where} which returns a 2-d
+ integer array of indices that indicate where the elements of
+ \var{a} are less than zero. Finally, those elements of \var{a} are
+ set to zero.
+
+ As a final example, consider once more the example involving the set of
+ \var{n} quadratic equations presented above. Suppose that we wish
+ to get rid of the coefficients of the previous example that
+ generated non-real solutions. Using an explicit \var{for} loop requires
+ code such as:
+#v+
+ variable i, j, nn, tmp_a, tmp_b, tmp_c;
+
+ nn = 0;
+ for (i = 0; i < n; i++)
+ if (index_array [i]) nn++;
+
+ tmp_a = Double_Type [nn];
+ tmp_b = Double_Type [nn];
+ tmp_c = Double_Type [nn];
+
+ j = 0;
+ for (i = 0; i < n; i++)
+ {
+ if (index_array [i])
+ {
+ tmp_a [j] = a[i];
+ tmp_b [j] = b[i];
+ tmp_c [j] = c[i];
+ j++;
+ }
+ }
+ a = tmp_a;
+ b = tmp_b;
+ c = tmp_c;
+#v-
+ Not only is this a lot of code, it is also clumsy and error-prone.
+ Using the \var{where} function, this task is trivial:
+#v+
+ variable i;
+ i = where (index_array != 0);
+ a = a[i];
+ b = b[i];
+ c = c[i];
+#v-
+
+ All the examples up to now assumed that the dimensions of the array
+ were known. Although the intrinsic function \var{length} may be
+ used to get the total number of elements of an array, it cannot be
+ used to get the individual dimensions of a multi-dimensional array.
+ However, the function \var{array_info} may be used to
+ get information about an array, such as its data type and size.
+ The function returns three values: the data type, the number of
+ dimensions, and an integer array containing the size
+ of each dimension. It may be used to determine the number of rows
+ of an array as follows:
+#v+
+ define num_rows (a)
+ {
+ variable dims, type, num_dims;
+
+ (dims, num_dims, type) = array_info (a);
+ return dims[0];
+ }
+#v-
+ The number of columns may be obtained in a similar manner:
+#v+
+ define num_cols (a)
+ {
+ variable dims, type, num_dims;
+
+ (dims, num_dims, type) = array_info (a);
+ if (num_dims > 1) return dims[1];
+ return 1;
+ }
+#v-
+
+ Another use of \var{array_info} is to create an array that has the
+ same number of dimensions as another array:
+#v+
+ define make_int_array (a)
+ {
+ variable dims, num_dims, type;
+
+ (dims, num_dims, type) = array_info (a);
+ return @Array_Type (Integer_Type, dims);
+ }
+#v-
+
+#%}}}
+
+#%}}}
+
+\chapter{Associative Arrays} #%{{{
+
+ An associative array differs from an ordinary array in the sense
+ that its size is not fixed and that is indexed by a string, called
+ the \em{key}. For example, consider:
+#v+
+ variable A = Assoc_Type [Integer_Type];
+ A["alpha"] = 1;
+ A["beta"] = 2;
+ A["gamma"] = 3;
+#v-
+ Here, \var{A} represents an associative array of integers
+ (\var{Integer_Type}) and three keys have been added to the array.
+
+ As the example suggests, an associative array may be created using
+ one of the following forms:
+\begin{tscreen}
+ Assoc_Type [\em{type}]
+ Assoc_Type [\em{type}, \em{default-value}]
+ Assoc_Type []
+\end{tscreen}
+ The last form returns an associative array of \var{Any_Type}
+ objects allowing any type of object to may be stored in
+ the array.
+
+ The form involving a \em{default-value} is useful for associating a
+ default value for non-existent array members. This feature is
+ explained in more detail below.
+
+ There are several functions that are specially designed to work
+ with associative arrays. These include:
+\begin{itemize}
+\item \var{assoc_get_keys}, which returns an ordinary array of strings
+ containing the keys in the array.
+
+\item \var{assoc_get_values}, which returns an ordinary array of the
+ values of the associative array.
+
+\item \var{assoc_key_exists}, which can be used to determine whether
+ or not a key exists in the array.
+
+\item \var{assoc_delete_key}, which may be used to remove a key (and
+ its value) from the array.
+\end{itemize}
+
+ To illustrate the use of an associative array, consider the problem
+ of counting the number of repeated occurrences of words in a list.
+ Let the word list be represented as an array of strings given by
+ \var{word_list}. The number of occurrences of each word may be
+ stored in an associative array as follows:
+#v+
+ variable a, word;
+ a = Assoc_Type [Integer_Type];
+ foreach (word_list)
+ {
+ word = ();
+ if (0 == assoc_key_exists (a, word))
+ a[word] = 0;
+ a[word]++; % same as a[word] = a[word] + 1;
+ }
+#v-
+ Note that \var{assoc_key_exists} was necessary to determine whether
+ or not a word was already added to the array in order to properly
+ initialize it. However, by creating the associative array with a
+ default value of \exmp{0}, the above code may be simplified to
+#v+
+ variable a, word;
+ a = Assoc_Type [Integer_Type, 0];
+ foreach (word_list)
+ {
+ word = ();
+ a[word]++;
+ }
+#v-
+
+
+#%}}}
+
+\chapter{Structures and User-Defined Types} #%{{{
+
+ A \em{structure} is a heterogeneous container object, i.e., it is
+ an object with elements whose values do not have to be of the same
+ data type. The elements or fields of a structure are named, and
+ one accesses a particular field of the structure via the field
+ name. This should be contrasted with an array whose values are of
+ the same type, and whose elements are accessed via array indices.
+
+ A \em{user-defined} data type is a structure with a fixed set of
+ fields defined by the user.
+
+\sect{Defining a Structure}
+
+ The \kw{struct} keyword is used to define a structure. The syntax
+ for this operation is:
+\begin{tscreen}
+ struct {\em{field-name-1}, \em{field-name-2}, ... \em{field-name-N}};
+\end{tscreen}
+ This creates and returns a structure with \em{N} fields whose names
+ are specified by \em{field-name-1}, \em{field-name-2}, ...,
+ \em{field-name-N}. When a structure is created, all its fields are
+ initialized to \var{NULL}.
+
+ For example,
+#v+
+ variable t = struct { city_name, population, next };
+#v-
+ creates a structure with three fields and assigns it to the
+ variable \var{t}.
+
+ Alternatively, a structure may be created by dereferencing
+ \var{Struct_Type}. For example, the above structure may also be
+ created using one of the two forms:
+#v+
+ t = @Struct_Type ("city_name", "population", "next");
+ t = @Struct_Type (["city_name", "population", "next"]);
+#v-
+ These are useful when creating structures dynamically where one does
+ not know the name of the fields until run-time.
+
+ Like arrays, structures are passed around via a references. Thus,
+ in the above example, the value of \var{t} is a reference to the
+ structure. This means that after execution of
+#v+
+ variable u = t;
+#v-
+ \em{both} \var{t} and \var{u} refer to the \em{same} structure,
+ since only the reference was used in the assignment. To actually
+ create a new copy of the structure, use the \em{dereference}
+ operator, e.g.,
+#v+
+ variable u = @t;
+#v-
+
+\sect{Accessing the Fields of a Structure}
+
+ The dot (\var{.}) operator is used to specify the particular
+ field of structure. If \var{s} is a structure and \var{field_name}
+ is a field of the structure, then \exmp{s.field_name} specifies
+ that field of \var{s}. This specification can be used in
+ expressions just like ordinary variables. Again, consider
+#v+
+ variable t = struct { city_name, population, next };
+#v-
+ described in the last section. Then,
+#v+
+ t.city_name = "New York";
+ t.population = 13000000;
+ if (t.population > 200) t = t.next;
+#v-
+ are all valid statements involving the fields of \var{t}.
+
+\sect{Linked Lists}
+
+ One of the most important uses of structures is to create a
+ \em{dynamic} data structure such as a \em{linked-list}. A
+ linked-list is simply a chain of structures that are linked together
+ such that one structure in the chain is the value of a field of the
+ previous structure in the chain. To be concrete, consider the
+ structure discussed earlier:
+#v+
+ variable t = struct { city_name, population, next };
+#v-
+ and suppose that we desire to create a list of such structures.
+ The purpose of the \var{next} field is to provide the link to the
+ next structure in the chain. Suppose that there exists a function,
+ \var{read_next_city}, that reads city names and populations from a
+ file. Then we can create the list via:
+#v+
+ define create_population_list ()
+ {
+ variable city_name, population, list_root, list_tail;
+ variable next;
+
+ list_root = NULL;
+ while (read_next_city (&city_name, &population))
+ {
+ next = struct {city_name, population, next };
+
+ next.city_name = city_name;
+ next.population = population;
+ next.next = NULL;
+
+ if (list_root == NULL)
+ list_root = next;
+ else
+ list_tail.next = next;
+
+ list_tail = next;
+ }
+ return list_root;
+ }
+#v-
+ In this function, the variables \var{list_root} and \var{list_tail}
+ represent the beginning and end of the list, respectively. As long
+ as \var{read_next_city} returns a non-zero value, a new structure is
+ created, initialized, and then appended to the list via the
+ \var{next} field of the \var{list_tail} structure. On the first
+ time through the loop, the list is created via the assignment to the
+ \var{list_root} variable.
+
+ This function may be used as follows:
+#v+
+ variable Population_List = create_population_list ();
+ if (Population_List == NULL) error ("List is empty");
+#v-
+ We can create other functions that manipulate the list. An example is
+ a function that finds the city with the largest population:
+#v+
+ define get_largest_city (list)
+ {
+ variable largest;
+
+ largest = list;
+ while (list != NULL)
+ {
+ if (list.population > largest.population)
+ largest = list;
+ list = list.next;
+ }
+ return largest.city_name;
+ }
+
+ vmessage ("%s is the largest city in the list",
+ get_largest_city (Population_List)));
+#v-
+ The \var{get_largest_city} is a typical example of how one traverses
+ a linear linked-list by starting at the head of the list and
+ successively moves to the next element of the list via the
+ \var{next} field.
+
+ In the previous example, a \kw{while} loop was used to traverse the
+ linked list. It is faster to use a \kw{foreach} loop for this:
+#v+
+ define get_largest_city (list)
+ {
+ variable largest, elem;
+
+ largest = list;
+ foreach (list)
+ {
+ elem = ();
+ if (item.population > largest.population)
+ largest = item;
+ }
+ return largest.city_name;
+ }
+#v-
+ Here a \kw{foreach} loop has been used to walk the list via its
+ \exmp{next} field. If the field name was not \exmp{next}, then it
+ would have been necessary to use the \kw{using} form of the
+ \kw{foreach} statement. For example, if the field name implementing the
+ linked list was \exmp{next_item}, then
+#v+
+ foreach (list) using ("next_item")
+ {
+ elem = ();
+ .
+ .
+ }
+#v-
+ would have been used. In other words, unless otherwise indicated
+ via the \kw{using} clause, \kw{foreach} walks the list using a field
+ named \exmp{next}.
+
+ Now consider a function that sorts the list according to population.
+ To illustrate the technique, a \em{bubble-sort} will be used, not
+ because it is efficient, it is not, but because it is simple and
+ intuitive.
+#v+
+ define sort_population_list (list)
+ {
+ variable changed;
+ variable node, next_node, last_node;
+ do
+ {
+ changed = 0;
+ node = list;
+ next_node = node.next;
+ last_node = NULL;
+ while (next_node != NULL)
+ {
+ if (node.population < next_node.population)
+ {
+ % swap node and next_node
+ node.next = next_node.next;
+ next_node.next = node;
+ if (last_node != NULL)
+ last_node.next = next_node;
+
+ if (list == node) list = next_node;
+ node = next_node;
+ next_node = node.next;
+ changed++;
+ }
+ last_node = node;
+ node = next_node;
+ next_node = next_node.next;
+ }
+ }
+ while (changed);
+
+ return list;
+ }
+#v-
+ Note the test for equality between \var{list} and \var{node}, i.e.,
+#v+
+ if (list == node) list = next_node;
+#v-
+ It is important to appreciate the fact that the values of these
+ variables are references to structures, and that the
+ comparison only compares the references and \em{not} the actual
+ structures they reference. If it were not for this, the algorithm
+ would fail.
+
+\sect{Defining New Types}
+
+ A user-defined data type may be defined using the \kw{typedef}
+ keyword. In the current implementation, a user-defined data type
+ is essentially a structure with a user-defined set of fields. For
+ example, in the previous section a structure was used to represent
+ a city/population pair. We can define a data type called
+ \var{Population_Type} to represent the same information:
+#v+
+ typedef struct
+ {
+ city_name,
+ population
+ } Population_Type;
+#v-
+ This data type can be used like all other data types. For example,
+ an array of Population_Type types can be created,
+#v+
+ variable a = Population_Type[10];
+#v-
+ and `populated' via expressions such as
+#v+
+ a[0].city_name = "Boston";
+ a[0].population = 2500000;
+#v-
+ The new type \var{Population_Type} may also be used with the
+ \var{typeof} function:
+#v+
+ if (Population_Type = typeof (a)) city = a.city_name;
+#v-
+ The dereference \var{@} may be used to create an instance of the
+ new type:
+#v+
+ a = @Population_Type;
+ a.city_name = "Calcutta";
+ a.population = 13000000;
+#v-
+
+
+#%}}}
+
+\chapter{Error Handling} #%{{{
+
+ Many intrinsic functions signal errors in the event of failure.
+ User defined functions may also generate an error condition via the
+ \var{error} function. Depending upon the severity of the error, it
+ can be caught and cleared using a construct called an
+ \em{error-block}.
+
+\sect{Error-Blocks}
+
+ When the interpreter encounters a recoverable run-time error, it
+ will return to top-level by \em{unwinding} its function call
+ stack. Any error-blocks that it encounters as part of this
+ unwinding process will get executed. Errors such as syntax errors
+ and memory allocation errors are not recoverable, and error-blocks
+ will not get executed when such errors are encountered.
+
+ An error-block is defined using the syntax
+#v+
+ ERROR_BLOCK { statement-list }
+#v-
+ where \em{statement-list} represents a list of statements that
+ comprise the error-block. A simple example of an error-block is
+#v+
+ define simple (a)
+ {
+ ERROR_BLOCK { message ("error-block executed"); }
+ if (a) error ("Triggering Error");
+ message ("hello");
+ }
+#v-
+ Executing this function via \exmp{simple(0)} will result in the
+ message \exmp{"hello"}. However, calling it using \exmp{simple(1)}
+ will generate an error that will be caught, but not cleared, by
+ the error-block and the \exmp{"error-block executed"} message will
+ result.
+
+ Error-blocks are never executed unless triggered by an error. The
+ only exception to this is when the user explicitly indicates that
+ the error-block in scope should execute. This is indicated by the
+ special keyword \var{EXECUTE_ERROR_BLOCK}. For example,
+ \var{simple} could be recoded as
+#v+
+ define simple (a)
+ {
+ variable err_string = "error-block executed";
+ ERROR_BLOCK { message (err_string); }
+ if (a) error ("Triggering Error");
+ err_string = "hello";
+ EXECUTE_ERROR_BLOCK;
+ }
+#v-
+ Please note that \var{EXECUTE_ERROR_BLOCK} does not initiate an
+ error condition; it simply causes the error-block to be executed
+ and control will pass onto the next statement following the
+ \var{EXECUTE_ERROR_BLOCK} statement.
+
+\sect{Clearing Errors}
+
+ Once an error has been caught by an error-block, the error can be cleared
+ by the \var{_clear_error} function. After the error has been cleared,
+ execution will resume at the next statement at the level of the error block
+ following the statement that generated the error. For example, consider:
+#v+
+ define make_error ()
+ {
+ error ("Error condition created.");
+ message ("This statement is not executed.");
+ }
+
+ define test ()
+ {
+ ERROR_BLOCK
+ {
+ _clear_error ();
+ }
+ make_error ();
+ message ("error cleared.");
+ }
+#v-
+ Calling \var{test} will trigger an error in the \var{make_error}
+ function, but will get cleared in the \var{test} function. The
+ call-stack will unwind from \var{make_error} back into \var{test}
+ where the error-block will get executed. As a result, execution
+ resumes after the statement that makes the call to \var{make_error}
+ since this statement is at the same level as the error-block that
+ cleared the error.
+
+ Here is another example that illustrates how multiple error-blocks
+ work:
+#v+
+ define example ()
+ {
+ variable n = 0, s = "";
+ variable str;
+
+ ERROR_BLOCK {
+ str = sprintf ("s=%s,n=%d", s, n);
+ _clear_error ();
+ }
+
+ forever
+ {
+ ERROR_BLOCK {
+ s += "0";
+ _clear_error ();
+ }
+
+ if (n == 0) error ("");
+
+ ERROR_BLOCK {
+ s += "1";
+ }
+
+ if (n == 1) error ("");
+ n++;
+ }
+ return str;
+ }
+#v-
+ Here, three error-blocks have been declared. One has been declared
+ outside the \var{forever} loop and the other two have been declared
+ inside the \var{forever} loop. Each time through the loop, the variable
+ \var{n} is incremented and a different error-block is triggered. The
+ error-block that gets triggered is the last one encountered, since
+ that will be the one in scope. On the first time through the loop,
+ \var{n} will be zero and the first error-block in the loop will get
+ executed. This error block clears the error and execution resumes
+ following the \var{if} statement that triggered the error. The
+ variable \var{n} will get incremented to \exmp{1} and, on the
+ second cycle through the loop the second \var{if} statement
+ will trigger an error causing the second error-block to execute.
+ This time, the error is not cleared and the call-stack unwinds out
+ of the \var{forever} loop, at which point the error-block outside
+ the loop is in scope, causing it to execute. This error-block
+ prints out the values of the variables \var{s} and \var{n}. It
+ will clear the error and execution resumes on the statement
+ \em{following} the \var{forever} loop. The result of this
+ complicated series of events is that the function will return the
+ string \exmp{"s=01,n=1"}.
+
+#%}}}
+
+\chapter{Loading Files: evalfile and autoload}
+
+\chapter{File Input/Output} #%{{{
+
+ \slang provides built-in supports for two different I/O facilities.
+ The simplest interface is modeled upon the C language \var{stdio}
+ streams interface and consists of functions such as \var{fopen},
+ \var{fgets}, etc. The other interface is modeled on a lower level
+ POSIX interface consisting of functions such as \var{open},
+ \var{read}, etc. In addition to permitting more control, the lower
+ level interface permits one to access network objects as well as disk
+ files.
+
+\sect{Input/Output via stdio}
+\sect1{Stdio Overview}
+ The \var{stdio} interface consists of the following functions:
+\begin{itemize}
+\item \var{fopen}, which opens a file for read or writing.
+
+\item \var{fclose}, which closes a file opened by \var{fopen}.
+
+\item \var{fgets}, used to read a line from the file.
+
+\item \var{fputs}, which writes text to the file.
+
+\item \var{fprintf}, used to write formatted text to the file.
+
+\item \var{fwrite}, which may be used to write objects to the
+ file.
+
+\item \var{fread}, which reads a specified number of objects from
+ the file.
+
+\item \var{feof}, which is used to test whether the file pointer is at the
+ end of the file.
+
+\item \var{ferror}, which is used to see whether or not the stream
+ associated with the file has an error.
+
+\item \var{clearerr}, which clears the end-of-file and error
+ indicators for the stream.
+
+\item \var{fflush}, used to force all buffered data associated with
+ the stream to be written out.
+
+\item \var{ftell}, which is used to query the file position indicator
+ of the stream.
+
+\item \var{fseek}, which is used to set the position of the file
+ position indicator of the stream.
+
+\item \var{fgetslines}, which reads all the lines in a text file and
+ returns them as an array of strings.
+
+\end{itemize}
+
+ In addition, the interface supports the \var{popen} and \var{pclose}
+ functions on systems where the corresponding C functions are available.
+
+ Before reading or writing to a file, it must first be opened using
+ the \var{fopen} function. The only exceptions to this rule involves
+ use of the pre-opened streams: \var{stdin}, \var{stdout}, and
+ \var{stderr}. \var{fopen} accepts two arguments: a file name and a
+ string argument that indicates how the file is to be opened, e.g.,
+ for reading, writing, update, etc. It returns a \var{File_Type}
+ stream object that is used as an argument to all other functions of
+ the \var{stdio} interface. Upon failure, it returns \NULL. See the
+ reference manual for more information about \var{fopen}.
+
+\sect1{Stdio Examples}
+
+ In this section, some simple examples of the use of the \var{stdio}
+ interface is presented. It is important to realize that all the
+ functions of the interface return something, and that return value
+ must be dealt with.
+
+ The first example involves writing a function to count the number of
+ lines in a text file. To do this, we shall read in the lines, one by
+ one, and count them:
+#v+
+ define count_lines_in_file (file)
+ {
+ variable fp, line, count;
+
+ fp = fopen (file, "r"); % Open the file for reading
+ if (fp == NULL)
+ verror ("%s failed to open", file);
+
+ count = 0;
+ while (-1 != fgets (&line, fp))
+ count++;
+
+ () = fclose (fp);
+ return count;
+ }
+#v-
+ Note that \exmp{&line} was passed to the \var{fgets} function. When
+ \var{fgets} returns, \var{line} will contain the line of text read in
+ from the file. Also note how the return value from \var{fclose} was
+ handled.
+
+ Although the preceding example closed the file via \var{fclose},
+ there is no need to explicitly close a file because \slang will
+ automatically close the file when it is no longer referenced. Since
+ the only variable to reference the file is \var{fp}, it would have
+ automatically been closed when the function returned.
+
+ Suppose that it is desired to count the number of characters in the
+ file instead of the number of lines. To do this, the \var{while}
+ loop could be modified to count the characters as follows:
+#v+
+ while (-1 != fgets (&line, fp))
+ count += strlen (line);
+#v-
+ The main difficulty with this approach is that it will not work for
+ binary files, i.e., files that contain null characters. For such
+ files, the file should be opened in \em{binary} mode via
+#v+
+ fp = fopen (file, "rb");
+#v-
+ and then the data read in using the \var{fread} function:
+#v+
+ while (-1 != fread (&line, Char_Type, 1024, fp))
+ count += bstrlen (line);
+#v-
+ The \var{fread} function requires two additional arguments: the type
+ of object to read (\var{Char_Type} in the case), and the number of
+ such objects to read. The function returns the number of objects
+ actually read, or -1 upon failure. The \var{bstrlen} function was
+ used to compute the length of \var{line} because for \var{Char_Type}
+ or \var{UChar_Type} objects, the \var{fread} function assigns a
+ \em{binary} string (\var{BString_Type}) to \var{line}.
+
+ The \kw{foreach} construct also works with \var{File_Type} objects.
+ For example, the number of characters in a file may be counted via
+#v+
+ foreach (fp) using ("char")
+ {
+ ch = ();
+ count++;
+ }
+#v-
+ To count the number of lines, one can use:
+#v+
+ foreach (fp) using ("line")
+ {
+ line = ();
+ num_lines++;
+ count += strlen (line);
+ }
+#v-
+ Often one is not interested in trailing whitespace in the lines of a
+ file. To have trailing whitespace automatically stripped from the
+ lines as they are read in, use the \exmp{"wsline"} form, e.g.,
+#v+
+ foreach (fp) using ("wsline")
+ {
+ line = ();
+ .
+ .
+ }
+#v-
+
+ Finally, it should be mentioned that none of these examples should
+ be used to count the number of bytes in a file when that
+ information is more readily accessible by another means. For
+ example, it is preferable to get this information via the
+ \var{stat_file} function:
+#v+
+ define count_chars_in_file (file)
+ {
+ variable st;
+
+ st = stat_file (file);
+ if (st == NULL)
+ error ("stat_file failed.");
+ return st.st_size;
+ }
+#v-
+
+\sect{POSIX I/O}
+
+\sect{Advanced I/O techniques}
+
+ The previous examples illustrate how to read and write objects of a
+ single data-type from a file, e.g.,
+#v+
+ num = fread (&a, Double_Type, 20, fp);
+#v-
+ would result in a \exmp{Double_Type[num]} array being assigned to
+ \var{a} if successful. However, suppose that the binary data file
+ consists of numbers in a specified byte-order. How can one read
+ such objects with the proper byte swapping? The answer is to use
+ the \var{fread} function to read the objects as \var{Char_Type} and
+ then \em{unpack} the resulting string into the specified data type,
+ or types. This process is facilitated using the \var{pack} and
+ \var{unpack} functions.
+
+ The \var{pack} function follows the syntax
+\begin{tscreen}
+ BString_Type pack (\em{format-string}, \em{item-list});
+\end{tscreen}
+ and combines the objects in the \em{item-list} according to
+ \em{format-string} into a binary string and returns the result.
+ Likewise, the \var{unpack} function may be used to convert a binary
+ string into separate data objects:
+\begin{tscreen}
+ (\em{variable-list}) = unpack (\em{format-string}, \em{binary-string});
+\end{tscreen}
+
+ The format string consists of one or more data-type specification
+ characters, and each may be followed by an optional decimal length
+ specifier. Specifically, the data-types are specified according to
+ the following table:
+#v+
+ c char
+ C unsigned char
+ h short
+ H unsigned short
+ i int
+ I unsigned int
+ l long
+ L unsigned long
+ j 16 bit int
+ J 16 unsigned int
+ k 32 bit int
+ K 32 bit unsigned int
+ f float
+ d double
+ F 32 bit float
+ D 64 bit float
+ s character string, null padded
+ S character string, space padded
+ x a null pad character
+#v-
+ A decimal length specifier may follow the data-type specifier. With
+ the exception of the \var{s} and \var{S} specifiers, the length
+ specifier indicates how many objects of that data type are to be
+ packed or unpacked from the string. When used with the \var{s} or
+ \var{S} specifiers, it indicates the field width to be used. If the
+ length specifier is not present, the length defaults to one.
+
+ With the exception of \var{c}, \var{C}, \var{s}, \var{S}, and
+ \var{x}, each of these may be prefixed by a character that indicates
+ the byte-order of the object:
+#v+
+ > big-endian order (network order)
+ < little-endian order
+ = native byte-order
+#v-
+ The default is native byte order.
+
+ Here are a few examples that should make this more clear:
+#v+
+ a = pack ("cc", 'A', 'B'); % ==> a = "AB";
+ a = pack ("c2", 'A', 'B'); % ==> a = "AB";
+ a = pack ("xxcxxc", 'A', 'B'); % ==> a = "\0\0A\0\0B";
+ a = pack ("h2", 'A', 'B'); % ==> a = "\0A\0B" or "\0B\0A"
+ a = pack (">h2", 'A', 'B'); % ==> a = "\0\xA\0\xB"
+ a = pack ("<h2", 'A', 'B'); % ==> a = "\0B\0A"
+ a = pack ("s4", "AB", "CD"); % ==> a = "AB\0\0"
+ a = pack ("s4s2", "AB", "CD"); % ==> a = "AB\0\0CD"
+ a = pack ("S4", "AB", "CD"); % ==> a = "AB "
+ a = pack ("S4S2", "AB", "CD"); % ==> a = "AB CD"
+#v-
+
+ When unpacking, if the length specifier is greater than one, then an
+ array of that length will be returned. In addition, trailing
+ whitespace and null character are stripped when unpacking an object
+ given by the \var{S} specifier. Here are a few examples:
+#v+
+ (x,y) = unpack ("cc", "AB"); % ==> x = 'A', y = 'B'
+ x = unpack ("c2", "AB"); % ==> x = ['A', 'B']
+ x = unpack ("x<H", "\0\xAB\xCD"); % ==> x = 0xCDABuh
+ x = unpack ("xxs4", "a b c\0d e f"); % ==> x = "b c\0"
+ x = unpack ("xxS4", "a b c\0d e f"); % ==> x = "b c"
+#v-
+
+\sect1{Example: Reading /var/log/wtmp}
+
+ Consider the task of reading the Unix system file
+ \var{/var/log/utmp}, which contains login records about who logged
+ onto the system. This file format is documented in section 5 of the
+ online Unix man pages, and consists of a sequence of entries
+ formatted according to the C structure \var{utmp} defined in the
+ \var{utmp.h} C header file. The actual details of the structure
+ may vary from one version of Unix to the other. For the purposes of
+ this example, consider its definition under the Linux operating
+ system running on an Intel processor:
+#v+
+ struct utmp {
+ short ut_type; /* type of login */
+ pid_t ut_pid; /* pid of process */
+ char ut_line[12]; /* device name of tty - "/dev/" */
+ char ut_id[2]; /* init id or abbrev. ttyname */
+ time_t ut_time; /* login time */
+ char ut_user[8]; /* user name */
+ char ut_host[16]; /* host name for remote login */
+ long ut_addr; /* IP addr of remote host */
+ };
+#v-
+ On this system, \var{pid_t} is defined to be an \var{int} and
+ \var{time_t} is a \var{long}. Hence, a format specifier for the
+ \var{pack} and \var{unpack} functions is easily constructed to be:
+#v+
+ "h i S12 S2 l S8 S16 l"
+#v-
+ However, this particular definition is naive because it does not
+ allow for structure padding performed by the C compiler in order to
+ align the data types on suitable word boundaries. Fortunately, the
+ intrinsic function \var{pad_pack_format} may be used to modify a
+ format by adding the correct amount of padding in the right places.
+ In fact, \var{pad_pack_format} applied to the above format on an
+ Intel-based Linux system produces the result:
+#v+
+ "h x2 i S12 S2 x2 l S8 S16 l"
+#v-
+ Here we see that 4 bytes of padding were added.
+
+ The other missing piece of information is the size of the structure.
+ This is useful because we would like to read in one structure at a
+ time using the \var{fread} function. Knowing the size of the
+ various data types makes this easy; however it is even easier to use
+ the \var{sizeof_pack} intrinsic function, which returns the size (in
+ bytes) of the structure described by the pack format.
+
+ So, with all the pieces in place, it is rather straightforward to
+ write the code:
+#v+
+ variable format, size, fp, buf;
+
+ typedef struct
+ {
+ ut_type, ut_pid, ut_line, ut_id,
+ ut_time, ut_user, ut_host, ut_addr
+ } UTMP_Type;
+
+ format = pad_pack_format ("h i S12 S2 l S8 S16 l");
+ size = sizeof_pack (format);
+
+ define print_utmp (u)
+ {
+
+ () = fprintf (stdout, "%-16s %-12s %-16s %s\n",
+ u.ut_user, u.ut_line, u.ut_host, ctime (u.ut_time));
+ }
+
+
+ fp = fopen ("/var/log/utmp", "rb");
+ if (fp == NULL)
+ error ("Unable to open utmp file");
+
+ () = fprintf (stdout, "%-16s %-12s %-16s %s\n",
+ "USER", "TTY", "FROM", "LOGIN@");
+
+ variable U = @UTMP_Type;
+
+ while (-1 != fread (&buf, Char_Type, size, fp))
+ {
+ set_struct_fields (U, unpack (format, buf));
+ print_utmp (U);
+ }
+
+ () = fclose (fp);
+#v-
+ A few comments about this example are in order. First of all, note
+ that a new data type called \var{UTMP_Type} was created, although
+ this was not really necessary. We also opened the file in binary
+ mode, but this too is optional under a Unix system where there is no
+ distinction between binary and text modes. The \var{print_utmp}
+ function does not print all of the structure fields. Finally, last
+ but not least, the return values from \var{fprintf} and \var{fclose}
+ were dealt with.
+
+#%}}}
+
+\chapter{Debugging} #%{{{
+
+ The current implementation provides no support for an interactive
+ debugger, although a future version will. Nevertheless, \slang has
+ several features that aid the programmer in tracking down problems,
+ including function call tracebacks and the tracing of function calls.
+ However, the biggest debugging aid stems from the fact that the
+ language is interpreted permitting one to easily add debugging
+ statements to the code.
+
+ To enable debugging information, add the lines
+#v+
+ _debug_info = 1;
+ _traceback = 1;
+#v-
+ to the top of the source file of the code containing the bug and the
+ reload the file. Setting the \var{_debug_info} variable to
+ \exmp{1} causes line number information to be compiled into the
+ functions when the file is loaded. The \var{_traceback} variable
+ controls whether or not traceback information should be generated.
+ If it is set to \exmp{1}, the values of local variables will be
+ dumped when the traceback is generated. Setting this variable
+ to \exmp{-1} will cause only function names to be reported in the
+ traceback.
+
+ Here is an example of a traceback report:
+#v+
+ S-Lang Traceback: error
+ S-Lang Traceback: verror
+ S-Lang Traceback: (Error occurred on line 65)
+ S-Lang Traceback: search_generic_search
+ Local Variables:
+ $0: Type: String_Type, Value: "Search forward:"
+ $1: Type: Integer_Type, Value: 1
+ $2: Type: Ref_Type, Value: _function_return_1
+ $3: Type: String_Type, Value: "abcdefg"
+ $4: Type: Integer_Type, Value: 1
+ S-Lang Traceback: (Error occurred on line 72)
+ S-Lang Traceback: search_forward
+#v-
+ There are several ways to read this report; perhaps the simplest is
+ to read it from the bottom. This report says that on line \exmp{72},
+ the \var{search_forward} function called the
+ \var{search_generic_search} function. On line \var{65} it called the
+ \verb{verror} function, which called \var{error}. The
+ \var{search_generic_search} function contains \var{5} local variables
+ and are represented symbolically as \exmp{$0} through \exmp{$4}.
+
+
+#%}}}
+
+#i regexp.tm
+
+\chapter{Future Directions} #%{{{
+
+ Several new features or enhancements to the \slang language are
+ planned for the next major release. In no particular order, these
+ include:
+\begin{itemize}
+ \item An interactive debugging facility.
+ \item Function qualifiers. These entities should already be
+ familiar to VMS users or to those who are familiar with the IDL
+ language. Basically, a qualifier is an optional argument that is
+ passed to a function, e.g., \exmp{plot(X,Y,/logx)}. Here
+ \exmp{/logx} is a qualifier that specifies that the plot function
+ should use a log scale for \exmp{x}.
+ \item File local variables and functions. A file local variable or
+ function is an object that is global to the file that defines it.
+ \item Multi-threading. Currently the language does not support
+ multiple threads.
+\end{itemize}
+
+
+#%}}}
+
+\appendix
+
+#i copyright.tm
+
+\end{\documentstyle}
diff --git a/libslang/doc/tm/slangfun.tm b/libslang/doc/tm/slangfun.tm
new file mode 100644
index 0000000..44ee6d9
--- /dev/null
+++ b/libslang/doc/tm/slangfun.tm
@@ -0,0 +1,121 @@
+#% -*- mode: tm; mode: fold; eval: .0 =TAB -*-
+#%{{{Macros
+
+#i linuxdoc.tm
+
+#d slang \bf{S-lang}
+#d kw#1 \tt{$1}
+#d exmp#1 \tt{$1}
+#d var#1 \tt{$1}
+
+#d ivar#1 \tt{$1}
+#d ifun#1 \tt{$1}
+#d cvar#1 \tt{$1}
+#d cfun#1 \tt{$1}
+#d svar#1 \tt{$1}
+#d sfun#1 \tt{$1}
+
+#d ldots ...
+#d chapter#1 <chapt>$1<p>
+#d preface <preface>
+#d tag#1 <tag>$1</tag>
+
+#d function#1 \sect{<bf>$1</bf>\label{$1}}<descrip>
+#d variable#1 \sect{<bf>$1</bf>\label{$1}}<descrip>
+#cd function#1 <p><bf>$1</bf>\label{$1}<p><descrip>
+#d synopsis#1 <tag> Synopsis </tag> $1
+#d keywords#1 <tag> Keywords </tag> $1
+#d usage#1 <tag> Usage </tag> <tt>$1</tt>
+#d description <tag> Description </tag>
+#d example <tag> Example </tag>
+#d notes <tag> Notes </tag>
+#d seealso#1 <tag> See Also </tag> <tt>$1</tt>
+#d r#1 \ref{$1}{$1}
+#d done </descrip><p>
+#d -1 <tt>-1</tt>
+#d 0 <tt>0</tt>
+#d 1 <tt>1</tt>
+#d 2 <tt>2</tt>
+#d 3 <tt>3</tt>
+#d 4 <tt>4</tt>
+#d 5 <tt>5</tt>
+#d 6 <tt>6</tt>
+#d 7 <tt>7</tt>
+#d 8 <tt>8</tt>
+#d 9 <tt>9</tt>
+#d NULL <tt>NULL</tt>
+#d documentstyle book
+
+
+#d user-manual \bf{A Guide to the S-Lang Language}
+
+
+#%}}}
+
+\linuxdoc
+\begin{\documentstyle}
+
+\title S-Lang Run-Time Library Reference: Version 1.4.0
+\author John E. Davis, \tt{davis@space.mit.edu}
+\date \__today__
+
+\toc
+
+\chapter{Array Functions}
+#i rtl/array.tm
+
+\chapter{Associative Array Functions}
+#i rtl/assoc.tm
+
+\chapter{Functions that Operate on Strings}
+#i rtl/strops.tm
+
+\chapter{Functions that Manipulate Structures}
+#i rtl/struct.tm
+
+\chapter{Informational Functions}
+#i rtl/info.tm
+
+\chapter{Mathematical Functions}
+#i rtl/math.tm
+
+\chapter{Message and Error Functions}
+#i rtl/message.tm
+
+\chapter{Time and Date Functions}
+#i rtl/time.tm
+
+\chapter{Data-Type Conversion Functions}
+#i rtl/type.tm
+
+\chapter{Stdio File I/O Functions}
+#i rtl/stdio.tm
+
+\chapter{Low-level POSIX I/O functions}
+#i rtl/posio.tm
+
+\chapter{Directory Functions}
+#i rtl/dir.tm
+
+\chapter{Functions that parse pathnames}
+#i rtl/ospath.tm
+
+\chapter{System Call Functions}
+#i rtl/posix.tm
+
+\chapter{Eval Functions}
+#i rtl/eval.tm
+
+\chapter{Module Functions}
+#i rtl/import.tm
+
+\chapter{Debugging Functions}
+#i rtl/debug.tm
+
+\chapter{Stack Functions}
+#i rtl/stack.tm
+
+\chapter{Miscellaneous Functions}
+#i rtl/misc.tm
+
+\end{\documentstyle}
diff --git a/libslang/doc/tm/tools/Makefile b/libslang/doc/tm/tools/Makefile
new file mode 100644
index 0000000..94ec197
--- /dev/null
+++ b/libslang/doc/tm/tools/Makefile
@@ -0,0 +1,46 @@
+# -*- sh -*-
+ELF=
+EXECS_TO_BUILD = tm2txt sl2tm
+EXECS_TO_INSTALL = tm2txt sl2tm
+SYMLINK_DIR=$(HOME)/sys/$(ARCH)/objs/slang/doc/tm/tools
+SRCDIR=$(HOME)/src/slang/doc/tm/tools
+OBJDIR=$(SRCDIR)/$(ARCH)objs#
+
+SLANGDIR=$(SRCDIR)/../../src
+EXECLIBS = -L$(SLANGDIR)/$(ARCH)$(ELF)objs -lslang -lm
+EXECINC = -I$(SLANGDIR)
+
+COMPILE_CMD=$(CC) -c $(CFLAGS) $(EXECINC)
+LINK_CMD=$(CC) $(LDFLAGS)
+
+all: $(OBJDIR) $(EXECS_TO_BUILD)
+clean:
+ $(RM) $(OBJDIR)/* *~ #*
+
+tm2txt: $(OBJDIR)/tm2txt
+ @echo tm2txt created in $(OBJDIR)
+$(OBJDIR)/tm2txt: $(OBJDIR)/tm2txt.o $(EXEC_EXTRA_OBJS)
+ cd $(OBJDIR); $(LINK_CMD) tm2txt.o -o tm2txt $(EXECLIBS)
+$(OBJDIR)/tm2txt.o: tm2txt.c $(tm2txt_O_DEP)
+ cd $(OBJDIR); $(COMPILE_CMD) $(SRCDIR)/tm2txt.c -o tm2txt.o
+sl2tm: $(OBJDIR)/sl2tm
+ @echo sl2tm created in $(OBJDIR)
+$(OBJDIR)/sl2tm: $(OBJDIR)/sl2tm.o $(EXEC_EXTRA_OBJS)
+ cd $(OBJDIR); $(LINK_CMD) sl2tm.o -o sl2tm $(EXECLIBS)
+$(OBJDIR)/sl2tm.o: sl2tm.c $(sl2tm_O_DEP)
+ cd $(OBJDIR); $(COMPILE_CMD) $(SRCDIR)/sl2tm.c -o sl2tm.o
+
+$(OBJDIR):
+ -mkdir $(OBJDIR)
+
+install: $(EXECS_TO_INSTALL)
+ @for x in $(EXECS_TO_INSTALL); do \
+ echo Installing $$x in $(BINDIR); \
+ $(INSTALL_CMD) $(OBJDIR)/$$x $(BINDIR); \
+ done
+
+symlinks:
+ -/bin/rm -f $(ARCH)objs
+ -mkdir -p $(SYMLINK_DIR)
+ ln -s $(SYMLINK_DIR) $(ARCH)objs
+
diff --git a/libslang/doc/tm/tools/README b/libslang/doc/tm/tools/README
new file mode 100644
index 0000000..627c3a2
--- /dev/null
+++ b/libslang/doc/tm/tools/README
@@ -0,0 +1,67 @@
+This directory includes two programs:
+
+tm2txt:
+ This program processes one or more specially formatted .tm
+ source files and writes the result on stdout. By specially
+ formatted, it is meant that the .tm files are formatted
+ into sections such as:
+
+\function{my_function}
+\synopsis{Short Description}
+\usage{int my_function (void);}
+\description
+ \var{my_function} does something special and returns an integer.
+\example
+ Here is an example of its use:
+#v+
+ if (-1 == my_function ())
+ exit (1);
+#v-
+\seealso{my_other_function, your_function}
+\done
+
+ Run this README file through tm2txt and see the result.
+
+
+sl2tm:
+ This program strips the specially formatted documentation described
+ above from C files and S-Lang files. Here is an example of how the
+ documentation would appear in the C source:
+
+/*%+
+ *\function{my_other_function}
+ *\synopsis{Just another function}
+ *\usage{int my_other_function(void)}
+ *\description
+ * \var{my_other_function} is similar to \var{my_function} except that
+ * it returns a \em{random} integer.
+ *\example
+ * Here is an example:
+ *#v+
+ * (void) my_other_function ();
+ *#v-
+ *\notes
+ * This function is obsolete. Use \var{my_new_function} instead.
+ *\seealso{my_function, my_new_function}
+ *%- Note that \done should not be used. `*%-' implies \done
+ */
+
+In S-Lang files, the format is similar:
+
+%!%+ Lines that start with this denotes the start of documentation
+%\function{my_other_function}
+%\synopsis{Just another function}
+%\usage{int my_other_function(void)}
+%\description
+% \var{my_other_function} is similar to \var{my_function} except that
+% it returns a \em{random} integer.
+%\example
+% Here is an example:
+%#v+
+% (void) my_other_function ();
+%#v-
+%\notes
+% This function is obsolete. Use \var{my_new_function} instead.
+%\seealso{my_function, my_new_function}
+%!%- Note that \done should not be used. `%!%-' implies \done
+
diff --git a/libslang/doc/tm/tools/sl2tm.c b/libslang/doc/tm/tools/sl2tm.c
new file mode 100644
index 0000000..9d8c3ab
--- /dev/null
+++ b/libslang/doc/tm/tools/sl2tm.c
@@ -0,0 +1,216 @@
+/* This program has a simple purpose: strip the documentation from
+ * one or more slang .sl files or .c files.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+typedef struct
+{
+ char *lang;
+ char *doc_start_string;
+ char *doc_end_string;
+ char *doc_prefix_string;
+}
+Doc_File_Type;
+
+Doc_File_Type Doc_Files [] =
+{
+ { "sl",
+ "%!%+",
+ "%!%-",
+ "%"
+ },
+ {
+ "c",
+ "/*%+",
+ " *%-",
+ " *"
+ },
+ {
+ NULL, NULL, NULL, NULL
+ }
+};
+
+
+static Doc_File_Type *get_doc_type (char *lang)
+{
+ Doc_File_Type *dt;
+
+ dt = Doc_Files;
+
+ while (dt->lang != NULL)
+ {
+ if (0 == strcmp (dt->lang, lang))
+ return dt;
+
+ dt++;
+ }
+ return NULL;
+}
+
+
+static char *Tm_Comment_String = "#c";
+
+static int doc_strip (char *file, FILE *in, FILE *out, Doc_File_Type *df)
+{
+ char line[1024];
+ char ch_start, ch_end, ch_prefix;
+ unsigned int start_len, end_len, prefix_len;
+ int level;
+ char *start, *end, *prefix;
+ unsigned int linenum;
+
+ if (df == NULL)
+ return -1;
+
+ start = df->doc_start_string;
+ end = df->doc_end_string;
+ prefix = df->doc_prefix_string;
+
+ ch_start = *start;
+ start_len = strlen (start);
+ ch_end = *end;
+ end_len = strlen (end);
+ ch_prefix = *prefix;
+ prefix_len = strlen (prefix);
+
+ linenum = 0;
+ level = 0;
+ while (NULL != fgets (line, sizeof (line), in))
+ {
+ linenum++;
+ if (level == 0)
+ {
+ if ((*line == ch_start)
+ && (0 == strncmp (line, start, start_len)))
+ {
+ level = 1;
+ fprintf (out, "%s __LINE__: %u\n", Tm_Comment_String, linenum);
+ }
+ continue;
+ }
+
+ if ((*line == ch_end)
+ && (0 == strncmp (line, end, end_len)))
+ {
+ fputs ("\\done\n", out);
+ level = 0;
+ continue;
+ }
+
+ if ((*line == ch_prefix)
+ && (0 == strncmp (line, prefix, prefix_len)))
+ fputs (line + prefix_len, out);
+ else
+ {
+ fprintf (stderr, "%s:%u: expecting %s\n", file, linenum, prefix);
+ fputs ("\\done\n", out);
+ return -1;
+ /* fputs (line, out); */
+ }
+ }
+ return 0;
+}
+
+static char *guess_language (char *file)
+{
+ unsigned int len;
+ char *f;
+
+ len = strlen (file);
+ f = file + len;
+
+ while ((f > file) && (*f != '.'))
+ f--;
+
+ if (*f == '.') f++;
+ if (0 == strcmp (f, "c")) return "c";
+ if (0 == strcmp (f, "sl")) return "sl";
+
+ return "sl"; /* default */
+}
+
+static void usage (char *pgm)
+{
+ fprintf (stderr, "Usage: %s [-c] [-sl] file.... > docfile\n", pgm);
+}
+
+int main (int argc, char **argv)
+{
+ FILE *fpin;
+ FILE *fpout;
+ char *pgm;
+ int i;
+ char *language;
+
+ pgm = "sl2tm";
+
+ fpout = stdout;
+
+
+ language = NULL;
+
+ for (i = 1; i < argc; i++)
+ {
+ if (*argv[i] != '-')
+ break;
+
+ if (0 == strcmp (argv[i], "-c"))
+ language = "c";
+ else if (0 == strcmp (argv[i], "-sl"))
+ language = "sl";
+ else
+ {
+ usage (pgm);
+ return 1;
+ }
+ }
+
+ if (i >= argc)
+ {
+ if (isatty (0))
+ {
+ usage (pgm);
+ return 1;
+ }
+
+ if (language == NULL) language = "sl";
+ (void) doc_strip ("<stdin>", stdin, fpout, get_doc_type (language));
+ return 0;
+ }
+
+ while (i < argc)
+ {
+ char *file;
+ char *lang;
+ Doc_File_Type *dt;
+
+ file = argv[i];
+ i++;
+
+ lang = language;
+
+ if ((lang == NULL)
+ && (NULL == (lang = guess_language (file))))
+ lang = "sl";
+
+ if (NULL == (dt = get_doc_type (lang)))
+ continue;
+
+ if (NULL == (fpin = fopen (file, "r")))
+ {
+ fprintf (stderr, "Unable to open %s -- skipping it.\n", file);
+ continue;
+ }
+
+ fprintf (stdout, "%s __FILE__: %s\n", Tm_Comment_String, file);
+ (void) doc_strip (file, fpin, fpout, dt);
+ fclose (fpin);
+ }
+
+ if (fpout != stdout) fclose (fpout);
+ return 0;
+}
diff --git a/libslang/doc/tm/tools/tm2txt.c b/libslang/doc/tm/tools/tm2txt.c
new file mode 100644
index 0000000..b1c4858
--- /dev/null
+++ b/libslang/doc/tm/tools/tm2txt.c
@@ -0,0 +1,726 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+
+/* This program is a quick hack to turn the run-time library .tm files into
+ * a decent looking ascii text file. The currently available SGML-tools are
+ * not up to my standards for doing that.
+ */
+
+static int Run_Silent;
+static int Top_Level;
+
+typedef struct
+{
+ char *name;
+ char *value;
+}
+Macro_String_Type;
+
+static Macro_String_Type Macro_Strings [] =
+{
+ {"slang", "S-Lang"},
+ {"jed", "jed"},
+ {"NULL", "NULL"},
+ {"-1", "-1"},
+ {"0", "0"},
+ {"1", "1"},
+ {"2", "2"},
+ {"3", "3"},
+ {"4", "4"},
+ {"5", "5"},
+ {"6", "6"},
+ {"7", "7"},
+ {"8", "8"},
+ {"9", "9"},
+ {NULL, NULL}
+};
+
+typedef struct Section_Type
+{
+ char *section_name;
+ int (*format_fun) (struct Section_Type *);
+ unsigned int flags;
+}
+Section_Type;
+
+static int format_function (Section_Type *);
+static int format_synopsis (Section_Type *);
+static int format_usage (Section_Type *);
+static int format_description (Section_Type *);
+static int format_example (Section_Type *);
+static int format_notes (Section_Type *);
+static int format_see_also (Section_Type *);
+static int format_done (Section_Type *);
+
+static Section_Type Sections [] =
+{
+ {
+ "function",
+ format_function,
+ 0
+ },
+ {
+ "synopsis",
+ format_synopsis,
+ 0
+ },
+ {
+ "usage",
+ format_usage,
+ 0
+ },
+ {
+ "description",
+ format_description,
+ 0
+ },
+ {
+ "example",
+ format_example,
+ 0
+ },
+ {
+ "notes",
+ format_notes,
+ 0
+ },
+ {
+ "seealso",
+ format_see_also,
+ 0
+ },
+ {
+ "done",
+ format_done,
+ 0
+ },
+ {
+ "variable",
+ format_function,
+ 0
+ },
+ {
+ NULL, NULL, 0
+ }
+};
+
+static FILE *Input_File_Ptr;
+static FILE *Output_File_Ptr;
+
+#define MAX_BUF_LEN 1024
+static char Input_Buffer [MAX_BUF_LEN];
+static unsigned int Line_Number;
+static int Input_Buffer_Pushed;
+static int Line_Type;
+static char *This_Filename;
+
+
+#define END_OF_FILE 1
+#define SECTION_LINE 2
+#define VERBATUM_LINE 3
+
+static char Source_File[MAX_BUF_LEN];
+
+static int set_source_file (char *s)
+{
+ strncpy (Source_File, s, MAX_BUF_LEN);
+ Source_File[MAX_BUF_LEN-1] = 0;
+ This_Filename = Source_File;
+ return 0;
+}
+
+static int set_source_linenum (char *s)
+{
+ unsigned int n;
+
+ if (1 == sscanf (s, "%u", &n))
+ Line_Number = n;
+
+ return 0;
+}
+
+static int unget_input (char *buf)
+{
+ if (buf != NULL)
+ {
+ char *inp = Input_Buffer;
+ while (*buf != 0)
+ {
+ *inp++ = *buf++;
+ }
+ *inp = 0;
+ }
+ Input_Buffer_Pushed++;
+ return 0;
+}
+
+
+static int begin_verbatum (void);
+static int end_verbatum (void);
+static int indent (unsigned int);
+
+static int verbatum_mode (void)
+{
+ begin_verbatum ();
+ while (NULL != fgets (Input_Buffer, MAX_BUF_LEN, Input_File_Ptr))
+ {
+ Line_Number++;
+
+ if (Input_Buffer[0] == '#')
+ {
+ if ((Input_Buffer[1] != 'v')
+ || (Input_Buffer[2] != '-'))
+ {
+ fprintf (stderr, "%s:%u:Expecting verbatum end\n", This_Filename, Line_Number);
+ return -1;
+ }
+ break;
+ }
+
+ indent (3);
+ fputs (Input_Buffer, stdout);
+ }
+ end_verbatum ();
+ return 0;
+}
+
+
+
+static int get_next_line (void)
+{
+ unsigned int len;
+
+ while (1)
+ {
+ if (Input_Buffer_Pushed == 0)
+ {
+ if (NULL == fgets (Input_Buffer, MAX_BUF_LEN, Input_File_Ptr))
+ {
+ Line_Type = END_OF_FILE;
+ return -1;
+ }
+ Line_Number++;
+ }
+
+ Input_Buffer_Pushed = 0;
+ len = strlen (Input_Buffer);
+ if (len && (Input_Buffer[len - 1] == '\n'))
+ Input_Buffer [len - 1] = 0;
+
+ switch (*Input_Buffer)
+ {
+ case ';':
+ case '%':
+ break;
+
+ case '#':
+ if (Input_Buffer[1] == 'v')
+ {
+ if (Input_Buffer[2] == '+')
+ {
+ if (-1 == verbatum_mode ())
+ return -1;
+ }
+ else
+ {
+ fprintf (stderr, "%s:%u:Expecting verbatum start\n", This_Filename, Line_Number);
+ return -1;
+ }
+ break;
+ }
+ if (Input_Buffer[1] == 'c')
+ {
+ if (0 == strncmp (Input_Buffer, "#c __FILE__: ", 13))
+ {
+ set_source_file (Input_Buffer + 13);
+ break;
+ }
+ if (0 == strncmp (Input_Buffer, "#c __LINE__: ", 13))
+ {
+ set_source_linenum (Input_Buffer + 13);
+ break;
+ }
+ break;
+ }
+
+ break;
+
+
+ case '\\':
+ Line_Type = SECTION_LINE;
+ return 1;
+
+ default:
+ Line_Type = 0;
+ return 0;
+ }
+ }
+}
+
+static Section_Type *get_section (char *buf)
+{
+ char *name;
+ Section_Type *sec;
+ int has_colon;
+
+ if (*buf == '\\') buf++;
+
+ name = buf;
+ has_colon = 0;
+ while (*buf != 0)
+ {
+ if ((*buf == '\n')
+ || (*buf == ' ')
+ || (*buf == '\t'))
+ {
+ *buf = 0;
+ break;
+ }
+ if (*buf == '{')
+ {
+ has_colon = 1;
+ *buf = 0;
+ break;
+ }
+ buf++;
+ }
+
+ sec = Sections;
+ while (1)
+ {
+ if (sec->section_name == NULL)
+ {
+ if (Run_Silent == 0)
+ fprintf (stderr, "%s:%u:Unknown section '%s'\n", This_Filename, Line_Number, name);
+ return NULL;
+ }
+
+ if (0 == strcmp (sec->section_name, name))
+ break;
+
+ sec++;
+ }
+
+ if (has_colon)
+ {
+ unget_input (buf + 1);
+ }
+
+ return sec;
+}
+
+
+static int process_file (FILE *fp)
+{
+ Section_Type *sec;
+
+ Input_File_Ptr = fp;
+ Output_File_Ptr = stdout;
+ Line_Number = 0;
+ Top_Level = 1;
+ Line_Type = 0;
+
+ while (1)
+ {
+ while ((Line_Type != SECTION_LINE)
+ && (Line_Type != END_OF_FILE))
+ get_next_line ();
+
+ if (Line_Type == END_OF_FILE)
+ break;
+
+ if (NULL == (sec = get_section (Input_Buffer)))
+ {
+ if (Run_Silent == 0)
+ fprintf (stderr, "%s:%u:Error ignored.\n", This_Filename, Line_Number);
+ get_next_line ();
+ continue;
+ }
+
+ if (sec->format_fun == NULL)
+ {
+ get_next_line ();
+ continue;
+ }
+
+ if (-1 == (*sec->format_fun)(sec))
+ {
+ fprintf (stderr, "%s:%u:Fatal error\n", This_Filename, Line_Number);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+static void usage (void)
+{
+ char *pgm = "tm2txt";
+
+ fprintf (stderr, "%s usage:\n", pgm);
+ fprintf (stderr, "%s [--help] [--quiet] [files...]\n", pgm);
+}
+
+int main (int argc, char **argv)
+{
+ if ((argc > 1)
+ && ((0 == strcmp (argv[1], "--help")) || (0 == strcmp (argv[1], "-h"))))
+ {
+ usage ();
+ return 1;
+ }
+
+ if ((argc > 1) && (0 == strcmp (argv[1], "--quiet")))
+ {
+ Run_Silent = 1;
+ argc--;
+ argv++;
+ }
+
+ if ((argc == 1) && isatty (fileno(stdin)))
+ {
+ usage ();
+ return 1;
+ }
+
+ if (argc == 1)
+ {
+ This_Filename = "<stdin>";
+ process_file (stdin);
+ }
+ else
+ {
+ int i;
+
+ for (i = 1; i < argc; i++)
+ {
+ char *file = argv[i];
+ FILE *fp;
+
+ if (NULL == (fp = fopen (file, "r")))
+ {
+ fprintf (stderr, "Unable to open %s, skipping it.\n", file);
+ continue;
+ }
+ This_Filename = file;
+
+ if (-1 == process_file (fp))
+ {
+ fprintf (stderr, "Fatal error encountered processing %s\n",
+ file);
+ fclose (fp);
+ return 1;
+ }
+
+ fclose (fp);
+ }
+ }
+
+ return 0;
+}
+
+static int write_boldface (char *s)
+{
+ fprintf (Output_File_Ptr, "%s", s);
+ return 0;
+}
+
+#if 0
+static int write_tt (char *s)
+{
+ fprintf (Output_File_Ptr, "`%s'", s);
+ return 0;
+}
+#endif
+static int newline (void)
+{
+ fputs ("\n", Output_File_Ptr);
+ return 0;
+}
+
+
+static int write_section_name (char *s)
+{
+ newline ();
+ fputs (" ", Output_File_Ptr);
+ write_boldface (s);
+ newline ();
+ return 0;
+}
+
+static char *write_verbatum_output (char *buf)
+{
+ while (*buf && (*buf != '}'))
+ {
+ if (*buf == '\\')
+ {
+ buf++;
+ if (*buf == 0)
+ break;
+ }
+
+ putc (*buf, Output_File_Ptr);
+ buf++;
+ }
+ if (*buf == '}') buf++;
+ return buf;
+}
+
+
+static char *write_macro (char *s)
+{
+ char *s1;
+ char ch;
+ Macro_String_Type *m;
+
+ s1 = s;
+ while ((ch = *s1) != 0)
+ {
+ if ((0 == isalnum (ch))
+ && (ch != '-')
+ && (ch != '_'))
+ break;
+
+ s1++;
+ }
+ *s1 = 0;
+
+ m = Macro_Strings;
+ while (m->name != NULL)
+ {
+ if (0 == strcmp (m->name, s))
+ {
+ fputs (m->value, Output_File_Ptr);
+ *s1 = ch;
+ return s1;
+ }
+ m++;
+ }
+ fprintf (Output_File_Ptr, "\\%s", s);
+ if (Run_Silent == 0)
+ fprintf (stderr, "%s:%u:%s not defined\n", This_Filename, Line_Number, s);
+ *s1 = ch;
+ return s1;
+}
+
+
+static int write_with_escape (char *buf)
+{
+ char ch;
+
+ while (1)
+ {
+ ch = *buf++;
+ switch (ch)
+ {
+ case 0:
+ return 0;
+
+ case '\\':
+ if (*buf == '\\')
+ {
+ putc (*buf, Output_File_Ptr);
+ buf++;
+ break;
+ }
+
+ if ((0 == strncmp ("var{", buf, 4))
+ || (0 == strncmp ("par{", buf, 4))
+ || (0 == strncmp ("fun{", buf, 4)))
+ {
+ putc ('`', Output_File_Ptr);
+ buf = write_verbatum_output (buf + 4);
+ putc ('\'', Output_File_Ptr);
+ break;
+ }
+
+ if ((0 == strncmp ("exmp{", buf, 5))
+ || (0 == strncmp ("ifun{", buf, 5))
+ || (0 == strncmp ("cfun{", buf, 5))
+ || (0 == strncmp ("sfun{", buf, 5))
+ || (0 == strncmp ("ivar{", buf, 5))
+ || (0 == strncmp ("cvar{", buf, 5))
+ || (0 == strncmp ("svar{", buf, 5)))
+ {
+ putc ('`', Output_File_Ptr);
+ buf = write_verbatum_output (buf + 5);
+ putc ('\'', Output_File_Ptr);
+ break;
+ }
+
+ if (0 == strncmp ("em{", buf, 3))
+ {
+ putc ('_', Output_File_Ptr);
+ buf = write_verbatum_output (buf + 3);
+ putc ('_', Output_File_Ptr);
+ break;
+ }
+
+ buf = write_macro (buf);
+ break;
+
+ default:
+ putc (ch, Output_File_Ptr);
+ break;
+
+ }
+ }
+}
+
+
+
+
+static int indent (unsigned int n)
+{
+ while (n)
+ {
+ putc (' ', Output_File_Ptr);
+ n--;
+ }
+
+ return 0;
+}
+
+static int write_line (void)
+{
+ char *s = Input_Buffer;
+ unsigned int min_indent = 3;
+
+ while ((*s == ' ') && min_indent)
+ {
+ s++;
+ min_indent--;
+ }
+
+ indent (min_indent);
+ write_with_escape (Input_Buffer);
+ newline ();
+ return 0;
+}
+
+
+static int format_function (Section_Type *sec)
+{
+ (void) sec;
+ if (Top_Level == 0)
+ {
+ fprintf (stderr, "%s:%u:\\function or \\variable not at top-level\n",
+ This_Filename, Line_Number);
+ fprintf (stderr, " Input line: %s\n", Input_Buffer);
+ return -1;
+ }
+ Top_Level = 0;
+
+ write_verbatum_output (Input_Buffer);
+ newline ();
+ get_next_line ();
+ return 0;
+}
+
+
+static int format_usage (Section_Type *sec)
+{
+ (void) sec;
+ write_section_name ("USAGE");
+ indent (3);
+ write_verbatum_output (Input_Buffer);
+ newline ();
+
+ get_next_line ();
+ return 0;
+}
+
+static int format_description (Section_Type *sec)
+{
+ (void) sec;
+ write_section_name ("DESCRIPTION");
+
+ while (0 == get_next_line ())
+ {
+ write_line ();
+ }
+ return 0;
+
+}
+
+static int format_example (Section_Type *sec)
+{
+ (void) sec;
+ write_section_name ("EXAMPLE");
+
+ while (0 == get_next_line ())
+ {
+ write_line ();
+ }
+ return 0;
+}
+
+static int format_notes (Section_Type *sec)
+{
+ (void) sec;
+ write_section_name ("NOTES");
+
+ while (0 == get_next_line ())
+ {
+ write_line ();
+ }
+ return 0;
+}
+
+static int format_see_also (Section_Type *sec)
+{
+ (void) sec;
+ write_section_name ("SEE ALSO");
+ indent (3);
+ write_verbatum_output (Input_Buffer);
+ newline ();
+ get_next_line ();
+ return 0;
+}
+
+
+int format_synopsis (Section_Type *sec)
+{
+ (void) sec;
+ write_section_name ("SYNOPSIS");
+ indent (3);
+ write_verbatum_output (Input_Buffer);
+ newline ();
+ get_next_line ();
+ return 0;
+}
+
+int format_done (Section_Type *sec)
+{
+ (void) sec;
+ if (Top_Level)
+ {
+ fprintf (stderr, "%s:%u:\\done seen at top-level\n",
+ This_Filename, Line_Number);
+ return -1;
+ }
+
+ fputs ("--------------------------------------------------------------\n",
+ Output_File_Ptr);
+ newline ();
+ while (0 == get_next_line ())
+ ;
+ Top_Level = 1;
+ return 0;
+}
+
+
+static int begin_verbatum (void)
+{
+ newline ();
+ return 0;
+}
+
+static int end_verbatum (void)
+{
+ newline ();
+ return 0;
+}