diff options
Diffstat (limited to 'libslang/doc')
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; +} |