diff options
Diffstat (limited to 'libslang/modules')
-rw-r--r-- | libslang/modules/Makefile.in | 56 | ||||
-rw-r--r-- | libslang/modules/README | 66 | ||||
-rw-r--r-- | libslang/modules/fcntl-module.c | 117 | ||||
-rwxr-xr-x | libslang/modules/grep | 171 | ||||
-rw-r--r-- | libslang/modules/newt-module.c | 91 | ||||
-rw-r--r-- | libslang/modules/newt.sl | 14 | ||||
-rw-r--r-- | libslang/modules/pcre-module.c | 618 | ||||
-rw-r--r-- | libslang/modules/select-module.c | 238 | ||||
-rw-r--r-- | libslang/modules/smg-module.c | 324 | ||||
-rw-r--r-- | libslang/modules/smg.sl | 70 | ||||
-rw-r--r-- | libslang/modules/template.c | 49 | ||||
-rw-r--r-- | libslang/modules/termios-module.c | 440 | ||||
-rw-r--r-- | libslang/modules/varray-module.c | 224 | ||||
-rw-r--r-- | libslang/modules/varray.sl | 37 |
14 files changed, 2515 insertions, 0 deletions
diff --git a/libslang/modules/Makefile.in b/libslang/modules/Makefile.in new file mode 100644 index 0000000..3d8a480 --- /dev/null +++ b/libslang/modules/Makefile.in @@ -0,0 +1,56 @@ +# -*- sh -*- +MODULES = smg-module.so termios-module.so select-module.so fcntl-module.so \ + varray-module.so pcre-module.so +#--------------------------------------------------------------------------- +CC_SHARED = @CC_SHARED@ +#--------------------------------------------------------------------------- +# Installation location of the slang library +#--------------------------------------------------------------------------- +prefix = @prefix@ +exec_prefix = @exec_prefix@ +SLANG_INC = -I@includedir@ +SLANG_LIB = -L@libdir@ -lslang +#--------------------------------------------------------------------------- +# Installation location of the modules +#--------------------------------------------------------------------------- +MODULE_INSTALL_DIR = @libdir@/slang/modules +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSDIR = ../autoconf/mkinsdir.sh +#--------------------------------------------------------------------------- +# DESTDIR is designed to facilitate making packages. Normally it is empty +#--------------------------------------------------------------------------- +DESTDIR = +DEST_MODULEDIR = $(DESTDIR)$(MODULE_INSTALL_DIR) +#--------------------------------------------------------------------------- +RPATH = @RPATH@ + +LIBS = $(RPATH) $(SLANG_LIB) $(DL_LIB) -lm +INCS = $(SLANG_INC) + +all: $(MODULES) + +smg-module.so: smg-module.c + $(CC_SHARED) $(INCS) smg-module.c -o smg-module.so $(LIBS) +newt-module.so: newt-module.c + $(CC_SHARED) $(INCS) newt-module.c -o newt-module.so -lnewt $(LIBS) +termios-module.so: termios-module.c + $(CC_SHARED) $(INCS) termios-module.c -o termios-module.so $(LIBS) +select-module.so: select-module.c + $(CC_SHARED) $(INCS) select-module.c -o select-module.so $(LIBS) +fcntl-module.so: fcntl-module.c + $(CC_SHARED) $(INCS) fcntl-module.c -o fcntl-module.so $(LIBS) +varray-module.so: varray-module.c + $(CC_SHARED) $(INCS) varray-module.c -o varray-module.so $(LIBS) +pcre-module.so: pcre-module.c + $(CC_SHARED) $(INCS) pcre-module.c -o pcre-module.so -lpcre $(LIBS) + +install: all + -$(MKINSDIR) $(DEST_MODULEDIR) + @for i in $(MODULES); \ + do \ + echo $(INSTALL_DATA) $$i $(DEST_MODULEDIR); \ + $(INSTALL_DATA) $$i $(DEST_MODULEDIR); \ + done +clean: + -/bin/rm -f $(MODULES) *~ diff --git a/libslang/modules/README b/libslang/modules/README new file mode 100644 index 0000000..f6b1292 --- /dev/null +++ b/libslang/modules/README @@ -0,0 +1,66 @@ +This directory contains some examples of dynamically loaded modules +that may be loaded via the `import' intrinsic function. If you choose +to build these modules, do so only AFTER installing the slang library +because the Makefile references the installed slang library location. + +The default installation location for the modules is in +$(prefix)/lib/slang/modules. + +-------------------------------------------------------------------- + +This directory contains some examples of dynamically loaded modules +that may be loaded via the `import' intrinsic function: + + import ("NAME"); + +This intrinsic function is available to applications that enable it +via a call to the `SLang_init_import' function. Of course, the OS +must provide support for dynamic linking. + +When a slang script contains a line such as + + import ("NAME"); + +or + + import ("NAME", "NAMESPACE"); + + +slang requests that the operating system dynamically link to a shared +object called NAME-module.so. Then the slang library will call the +function `init_NAME_ns' that NAME-module.so must define. This function +must have the prototype: + + int init_NAME_ns (char *namespace); + +and shall return 0 upon success, or -1 if an error occurred. The +namespace argument corresponds to the second (option) parameter of the +import intrinsic. This means that the user wishes to import the +module into the specified namespace. To this end, the module must +call one of the SLns_* functions to load intrinsics into a namespace. + +Optionally, the module may define a function called `deinit_NAME' that +will be called by the interpreter to deinitialize the module. This +function must have the prototype: + + void deinit_NAME (void); + +To ensure the correct prototypes for these functions, the module +should include the line: + + SLANG_MODULE(name); + +SLANG_MODULE is a macro that expands into function prototypes. + +See the examples in this directory for more information. + +To run these modules, use the slsh program in ../slsh/. +slsh.c is a program that embeds the interpreter and may be used to +test slang scripts. In fact, it may be used to create unix executable +scripts via, e.g., + +#! /usr/bin/env slsh + +as the first line of the script. See ../slsh/scripts subdirectory for +examples of this approach. + diff --git a/libslang/modules/fcntl-module.c b/libslang/modules/fcntl-module.c new file mode 100644 index 0000000..7b329ab --- /dev/null +++ b/libslang/modules/fcntl-module.c @@ -0,0 +1,117 @@ +/* Copyright (c) 2001 John E. Davis + * This file is part of the S-Lang library. + * + * You may distribute under the terms of either the GNU General Public + * License or the Perl Artistic License. + */ + +#include <stdio.h> +#include <slang.h> + +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> + +SLANG_MODULE(fcntl); + +static int check_and_set_errno (int e) +{ +#ifdef EINTR + if (e == EINTR) + return 0; +#endif + (void) SLerrno_set_errno (e); + return -1; +} + +static int do_fcntl_2 (SLFile_FD_Type *f, int cmd) +{ + int ret; + int fd; + + if (-1 == SLfile_get_fd (f, &fd)) + return -1; + + while ((-1 == (ret = fcntl (fd, cmd))) + && (0 == check_and_set_errno (errno))) + ; + + return ret; +} + +static int do_fcntl_3_int (SLFile_FD_Type *f, int cmd, int flags) +{ + int ret; + int fd; + + + if (-1 == SLfile_get_fd (f, &fd)) + return -1; + + while ((-1 == (ret = fcntl (fd, cmd, flags))) + && (0 == check_and_set_errno (errno))) + ; + + return ret; +} + +static int fcntl_getfd (SLFile_FD_Type *f) +{ + return do_fcntl_2 (f, F_GETFD); +} + +static int fcntl_setfd (SLFile_FD_Type *f, int *flags) +{ + return do_fcntl_3_int (f, F_SETFD, *flags); +} + +static int fcntl_getfl (SLFile_FD_Type *f) +{ + return do_fcntl_2 (f, F_GETFL); +} + +static int fcntl_setfl (SLFile_FD_Type *f, int *flags) +{ + return do_fcntl_3_int (f, F_SETFL, *flags); +} + +#define F SLANG_FILE_FD_TYPE +#define I SLANG_INT_TYPE +static SLang_Intrin_Fun_Type Fcntl_Intrinsics [] = +{ + MAKE_INTRINSIC_1("fcntl_getfd", fcntl_getfd, I, F), + MAKE_INTRINSIC_2("fcntl_setfd", fcntl_setfd, I, F, I), + MAKE_INTRINSIC_1("fcntl_getfl", fcntl_getfl, I, F), + MAKE_INTRINSIC_2("fcntl_setfl", fcntl_setfl, I, F, I), + + SLANG_END_INTRIN_FUN_TABLE +}; +#undef I +#undef F + +static SLang_IConstant_Type Fcntl_Consts [] = +{ + MAKE_ICONSTANT("FD_CLOEXEC", FD_CLOEXEC), + SLANG_END_ICONST_TABLE +}; + +int init_fcntl_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns; + + ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if ((-1 == SLns_add_intrin_fun_table (ns, Fcntl_Intrinsics, "__FCNTL__")) + || (-1 == SLns_add_iconstant_table (ns, Fcntl_Consts, NULL))) + return -1; + + return 0; +} + +/* This function is optional */ +void deinit_fcntl_module (void) +{ +} diff --git a/libslang/modules/grep b/libslang/modules/grep new file mode 100755 index 0000000..a8f97d6 --- /dev/null +++ b/libslang/modules/grep @@ -0,0 +1,171 @@ +#!/usr/bin/env slsh + +% This is a simple-minded implementation of a highlighting grep program +% designed to test the pcre module. +import ("pcre"); + +static define usage () +{ + ()=fprintf(stderr, "Usage: %s [-inl] pattern [files...]\n", __argv[0]); + exit (1); +} + +static variable MATCH = 1; +static variable LINENUM = 2; +static variable FILENAME = 4; +static variable Output_Format = 0; + +static define grep (file, p) +{ + variable fp; + + if (file == NULL) + fp = stdin; + else + fp = fopen (file, "r"); + + if (fp == NULL) + { + fprintf (stderr, "*** Unable to open %s\n", file); + return; + } + + variable linenum = 0; + foreach (fp) using ("line") + { + variable str = (); + linenum++; + + if (pcre_exec (p, str, 0)) + { + variable i0, i1, i; + + switch (Output_Format) + { + case FILENAME: + () = fprintf (stdout, "%s\n", file); + return; + } + { + case LINENUM: + () = fprintf (stdout, "%d\n", linenum); + continue; + } + { + case (MATCH|LINENUM): + + () = fprintf (stdout, "%d:", linenum); + } + { + case (LINENUM|FILENAME): + () = fprintf (stdout, "%s:%d\n", file, linenum); + continue; + } + { + case (LINENUM|FILENAME|MATCH): + () = fprintf (stdout, "%s:%d:", file, linenum); + } + { + case (FILENAME|MATCH): + () = fprintf (stdout, "%s:", file); + } + + do + { + i = pcre_nth_match (p, 0); + i0 = i[0]; + i1 = i[1]; + if (i1 <= i0) + break; + if (i0 > 0) + () = fprintf (stdout, "%s", str[[0:i0-1]]); + () = fprintf (stdout, "\e[7m%s\e[m", str[[i0:i1-1]]); + str = str[[i1:]]; + } + while (pcre_exec (p, str, 0)); + () = fprintf (stdout, "%s", str); + } + } +} + +static define main (argc, argv) +{ + variable i; + variable files, pattern; + variable options; + + i = 1; + files = NULL; + pattern = NULL; + options = 0; + Output_Format = MATCH; + + while (i < argc) + { + variable arg = __argv[i]; + i++; + + if (arg[0] == '-') + { + foreach (arg[[1:]]) + { + variable ch = (); + switch (ch) + { + case 'i': + options |= PCRE_CASELESS; + } + { + case 'l': + Output_Format &= ~MATCH; + Output_Format |= FILENAME; + } + { + case 'n': + Output_Format |= LINENUM; + } + { + () = fprintf (stderr, "Unsupported option: '%c'\n", ch); + exit (1); + } + } + continue; + } + + pattern = arg; + break; + } + + if (pattern == NULL) + usage (); + + variable p = pcre_compile (pattern, options); + + if (i == __argc) + { + if (isatty (stdin)) + usage (); + + Output_Format &= ~FILENAME; + grep (NULL, p); + return; + } + + files = argv[[i:]]; + + if (length(files) > 1) + Output_Format |= FILENAME; + + foreach (files) + { + variable f = (); + grep (f, p); + } +} + +public define slsh_main () +{ + main (__argc, __argv); + exit (0); +} + diff --git a/libslang/modules/newt-module.c b/libslang/modules/newt-module.c new file mode 100644 index 0000000..9788ed1 --- /dev/null +++ b/libslang/modules/newt-module.c @@ -0,0 +1,91 @@ +/* This module implements and interface to the Newt library */ +#include <stdio.h> +#include <slang.h> +#include <newt.h> + +SLANG_MODULE(newt); + +static int Ok_To_Draw; + +static void init (void) +{ + newtInit (); + Ok_To_Draw = 1; +} + +static void cls (void) +{ + if (Ok_To_Draw) + newtCls (); +} + +static void draw_root_text (int *c, int *r, char *s) +{ + if (Ok_To_Draw) + newtDrawRootText (*c, *r, s); +} + +static void open_window (int *c, int *r, int *dc, int *dr, char *title) +{ + if (Ok_To_Draw) + newtOpenWindow (*c, *r, *dc, *dr, title); +} + +static void refresh (void) +{ + if (Ok_To_Draw) + newtRefresh (); +} + +static void finished (void) +{ + if (Ok_To_Draw) + newtFinished (); + Ok_To_Draw = 0; +} + +#define I SLANG_INT_TYPE +#define S SLANG_STRING_TYPE + +static SLang_Intrin_Fun_Type Module_Funs [] = +{ + MAKE_INTRINSIC_0("newtInit", init, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("newtCls", cls, SLANG_VOID_TYPE), + MAKE_INTRINSIC_IIS("newtDrawRootText", draw_root_text, SLANG_VOID_TYPE), + MAKE_INTRINSIC_5("newtOpenWindow", open_window, SLANG_VOID_TYPE, I,I,I,I,S), + MAKE_INTRINSIC_0("newtRefresh", refresh, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("NewtFinished", finished, SLANG_VOID_TYPE), + + SLANG_END_TABLE +}; + +static SLang_Intrin_Var_Type Module_Variables [] = +{ + SLANG_END_TABLE +}; + +static SLang_IConstant_Type Module_Constants [] = +{ + SLANG_END_TABLE +}; + + +int init_newt_module_ns (char *ns) +{ + if ((-1 == SLns_add_intrin_fun_table (ns, Module_Funs, "__NEWT__")) + || (-1 == SLns_add_intrin_var_table (ns, Module_Variables, NULL)) + || (-1 == SLns_add_iconstant_table (ns, Module_Constants, NULL))) + return -1; + + Ok_To_Draw = 0; + + (void) SLang_add_cleanup_function (finished); + + return 0; +} + +/* This function is optional */ +void deinit_newt_module (void) +{ + finished (); +} diff --git a/libslang/modules/newt.sl b/libslang/modules/newt.sl new file mode 100644 index 0000000..0864d5e --- /dev/null +++ b/libslang/modules/newt.sl @@ -0,0 +1,14 @@ +import ("newt"); + +newtInit (); +%newtCls (); +newtDrawRootText (0, 0, "Root Text"); +newtOpenWindow (3,4,20, 20, "First Window"); +newtOpenWindow (8, 10,20, 20, "Second Window"); + +newtRefresh (); +sleep (5); +NewtFinished (); + +exit (0); + diff --git a/libslang/modules/pcre-module.c b/libslang/modules/pcre-module.c new file mode 100644 index 0000000..926e477 --- /dev/null +++ b/libslang/modules/pcre-module.c @@ -0,0 +1,618 @@ +#include <stdio.h> +#include <slang.h> +#include <pcre.h> + +SLANG_MODULE(pcre); + +static int PCRE_Type_Id; + +typedef struct +{ + pcre *p; + pcre_extra *extra; + int *ovector; + unsigned int ovector_len; /* must be a multiple of 3 */ + unsigned int num_matches; /* return value of pcre_exec (>= 1)*/ +} +PCRE_Type; + +static void free_pcre_type (PCRE_Type *pt) +{ + if (pt->ovector != NULL) + SLfree ((char *) pt->ovector); + + SLfree ((char *) pt); +} + +static SLang_MMT_Type *allocate_pcre_type (pcre *p, pcre_extra *extra) +{ + PCRE_Type *pt; + SLang_MMT_Type *mmt; + int ovector_len; + + pt = (PCRE_Type *) SLmalloc (sizeof (PCRE_Type)); + if (pt == NULL) + return NULL; + memset ((char *) pt, 0, sizeof (PCRE_Type)); + + pt->p = p; + pt->extra = extra; + + if (0 != pcre_fullinfo (p, extra, PCRE_INFO_CAPTURECOUNT, &ovector_len)) + { + free_pcre_type (pt); + SLang_verror (SL_INTRINSIC_ERROR, "pcre_fullinfo failed"); + return NULL; + } + + ovector_len += 1; /* allow for pattern matched */ + ovector_len *= 3; /* required to be multiple of 3 */ + if (NULL == (pt->ovector = (int *)SLmalloc (ovector_len * sizeof (int)))) + { + free_pcre_type (pt); + return NULL; + } + pt->ovector_len = ovector_len; + + if (NULL == (mmt = SLang_create_mmt (PCRE_Type_Id, (VOID_STAR) pt))) + { + free_pcre_type (pt); + return NULL; + } + return mmt; +} + +static int _pcre_compile_1 (char *pattern, int options) +{ + pcre *p; + pcre_extra *extra; + SLCONST char *err; + int erroffset; + unsigned char *table; + SLang_MMT_Type *mmt; + + table = NULL; + p = pcre_compile (pattern, options, &err, &erroffset, table); + if (NULL == p) + { + SLang_verror (SL_INTRINSIC_ERROR, "Error compiling pattern '%s' at offset %d: %s", + pattern, erroffset, err); + return -1; + } + + extra = pcre_study (p, 0, &err); + /* apparantly, a NULL return is ok */ + if (err != NULL) + { + SLang_verror (SL_INTRINSIC_ERROR, "pcre_study failed: %s", err); + pcre_free (p); + return -1; + } + + if (NULL == (mmt = allocate_pcre_type (p, extra))) + { + pcre_free ((char *) p); + pcre_free ((char *) extra); + return -1; + } + + if (-1 == SLang_push_mmt (mmt)) + { + SLang_free_mmt (mmt); + return -1; + } + return 0; +} + +static void _pcre_compile (void) +{ + char *pattern; + int options = 0; + + switch (SLang_Num_Function_Args) + { + case 2: + if (-1 == SLang_pop_integer (&options)) + return; + /* drop */ + case 1: + default: + if (-1 == SLang_pop_slstring (&pattern)) + return; + } + (void) _pcre_compile_1 (pattern, options); + SLang_free_slstring (pattern); +} + + + +/* returns number of matches */ +static int _pcre_exec_1 (PCRE_Type *pt, char *str, int pos, int options) +{ + int rc; + unsigned int len; + + pt->num_matches = 0; + len = strlen (str); + if ((unsigned int) pos > len) + return 0; + + rc = pcre_exec (pt->p, pt->extra, str, len, pos, + options, pt->ovector, pt->ovector_len); + + if (rc == PCRE_ERROR_NOMATCH) + return 0; + + if (rc <= 0) + { + SLang_verror (SL_INTRINSIC_ERROR, "pcre_exec returned %d", rc); + return -1; + } + pt->num_matches = (unsigned int) rc; + return rc; +} + +static int _pcre_exec (void) +{ + PCRE_Type *p; + SLang_MMT_Type *mmt; + char *str; + int pos = 0; + int options = 0; + int ret = -1; + + switch (SLang_Num_Function_Args) + { + case 4: + if (-1 == SLang_pop_integer (&options)) + return -1; + case 3: + if (-1 == SLang_pop_integer (&pos)) + return -1; + default: + if (-1 == SLang_pop_slstring (&str)) + return -1; + + if (NULL == (mmt = SLang_pop_mmt (PCRE_Type_Id))) + goto free_and_return; + p = SLang_object_from_mmt (mmt); + } + ret = _pcre_exec_1 (p, str, pos, options); + + free_and_return: + SLang_free_slstring (str); + SLang_free_mmt (mmt); + return ret; +} + + +static int get_nth_start_stop (PCRE_Type *pt, unsigned int n, + unsigned int *a, unsigned int *b) +{ + int start, stop; + + if (n >= pt->num_matches) + return -1; + + start = pt->ovector[2*n]; + stop = pt->ovector[2*n+1]; + if ((start < 0) || (stop < start)) + return -1; + + *a = (unsigned int) start; + *b = (unsigned int) stop; + return 0; +} + +static void _pcre_nth_match (PCRE_Type *pt, int *np) +{ + unsigned int start, stop; + SLang_Array_Type *at; + int two = 2; + int *data; + + if (-1 == get_nth_start_stop (pt, (unsigned int) *np, &start, &stop)) + { + SLang_push_null (); + return; + } + + if (NULL == (at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, &two, 1))) + return; + + data = (int *)at->data; + data[0] = (int)start; + data[1] = (int)stop; + (void) SLang_push_array (at, 1); +} + +static void _pcre_nth_substr (PCRE_Type *pt, char *str, int *np) +{ + unsigned int start, stop; + unsigned int len; + + len = strlen (str); + + if ((-1 == get_nth_start_stop (pt, (unsigned int) *np, &start, &stop)) + || (start > len) || (stop > len)) + { + SLang_push_null (); + return; + } + + str = SLang_create_nslstring (str + start, stop - start); + (void) SLang_push_string (str); + SLang_free_slstring (str); +} + +/* This function converts a slang RE to a pcre expression. It performs the + * following transformations: + * ( --> \( + * ) --> \) + * # --> \# + * | --> \| + * { --> \{ + * } --> \} + * \< --> \b + * \> --> \b + * \C --> (?i) + * \c --> (?-i) + * \( --> ( + * \) --> ) + * \{ --> { + * \} --> } + * Anything else? + */ +static char *_slang_to_pcre (char *slpattern) +{ + char *pattern, *p, *s; + unsigned int len; + int in_bracket; + char ch; + + len = strlen (slpattern); + pattern = SLmalloc (3*len + 1); + if (pattern == NULL) + return NULL; + + p = pattern; + s = slpattern; + in_bracket = 0; + while ((ch = *s++) != 0) + { + switch (ch) + { + case '{': + case '}': + case '(': + case ')': + case '#': + case '|': + if (0 == in_bracket) *p++ = '\\'; + *p++ = ch; + break; + + case '[': + in_bracket = 1; + *p++ = ch; + break; + + case ']': + in_bracket = 0; + *p++ = ch; + break; + + case '\\': + ch = *s++; + switch (ch) + { + case 0: + s--; + break; + + case '<': + case '>': + *p++ = '\\'; *p++ = 'b'; + break; + + case '(': + case ')': + case '{': + case '}': + *p++ = ch; + break; + + case 'C': + *p++ = '('; *p++ = '?'; *p++ = 'i'; *p++ = ')'; + break; + case 'c': + *p++ = '('; *p++ = '?'; *p++ = '-'; *p++ = 'i'; *p++ = ')'; + break; + + default: + *p++ = '\\'; + *p++ = ch; + } + break; + + default: + *p++ = ch; + break; + } + } + *p = 0; + + s = SLang_create_slstring (pattern); + SLfree (pattern); + return s; +} + +static void slang_to_pcre (char *pattern) +{ + /* NULL ok in code below */ + pattern = _slang_to_pcre (pattern); + (void) SLang_push_string (pattern); + SLang_free_slstring (pattern); +} + +static void destroy_pcre (SLtype type, VOID_STAR f) +{ + PCRE_Type *pt; + (void) type; + + pt = (PCRE_Type *) f; + if (pt->extra != NULL) + pcre_free ((char *) pt->extra); + if (pt->p != NULL) + pcre_free ((char *) pt->p); + free_pcre_type (pt); +} + +#define DUMMY_PCRE_TYPE 255 +#define P DUMMY_PCRE_TYPE +#define I SLANG_INT_TYPE +#define V SLANG_VOID_TYPE +#define S SLANG_STRING_TYPE +static SLang_Intrin_Fun_Type PCRE_Intrinsics [] = +{ + MAKE_INTRINSIC_0("pcre_compile", _pcre_compile, V), +/*%+ + *\function{pcre_compile} + *\synopsis{Compile a regular expression} + *\usage{PCRE_Type pcre_compile (String_Type pattern [, Int_Type options])} + *\description + * The \var{pcre_compile} function compiles a PCRE style regular expression + * and returns the result. The optional \var{options} argument may be used + * to provide addition information affecting the compilation of the pattern. + * Specifically, it is a bit-mapped value formed from the logical-or of zero + * or more of the following symbolic constants: + *#v+ + * PCRE_ANCHORED Force the match to be at the start of a string + * PCRE_CASELESS Matches are to be case-insensitive + * PCRE_DOLLAR_ENDONLY (See PCRE docs for more information) + * PCRE_DOTALL The dot pattern matches all characters + * PCRE_EXTENDED Ignore whitespace in the pattern + * PCRE_EXTRA (See PCRE docs for features this activates) + * PCRE_MULTILINE Treat the subject string as multi-lines + * PCRE_UNGREEDY Make the matches greedy + * PCRE_UTF8 Regard the pattern and subject strings as UTF-8 + *#v- + * Many of these flags may be set within the pattern itself. See the PCRE + * library documentation for more information about the precise details + * of these flags and the supported regular expressions. + * + * Upon success, this function returns a \var{PCRE_Type} object representing + * the compiled patterned. If compilation fails, an error will be thrown. + *\seealso{pcre_exec, pcre_nth_match, pcre_nth_substr} + *%- + */ + MAKE_INTRINSIC_0("pcre_exec", _pcre_exec, I), +/*%+ + *\function{pcre_exec} + *\synopsis{Match a string against a compiled PCRE pattern} + *\usage{Int_Type pcre_exec(p, str [,pos [,options]]); + *#v+ + * PCRE_Type p; + * String_Type str; + * Int_Type pos, options; + *#v- + *\description + * The \var{pcre_exec} function applies a pre-compiled pattern \var{p} to a + * string \var{str} and returns the result of the match. The optional third + * argument \var{pos} may be used to specify the point, as an offset from the + * start of the string, where matching is to start. The fourth argument, if + * present, may be used to provide additional information about how matching + * is to take place. Its value may be specified as a logical-or of zero or + * more of the following flags: + *#v+ + * PCRE_NOTBOL + * The first character in the string is not at the beginning of a line. + * PCRE_NOTEOL + * The last character in the string is not at the end of a line. + * PCRE_NOTEMPTY + * An empty string is not a valid match. + *#v- + * See the PCRE library documentation for more information about the meaning + * of these flags. + * + * Upon success, this function returns a positive integer equal to 1 plus the + * number of so-called captured substrings. It returns 0 if the pattern + * fails to match the string. + *\seealso{pcre_compile, pcre_nth_match, pcre_nth_substr} + *%- + */ + MAKE_INTRINSIC_2("pcre_nth_match", _pcre_nth_match, V, P, I), +/*%+ + *\function{pcre_nth_match} + *\synopsis{Return the location of the nth match of a PCRE} + *\usage{Int_Type[2] pcre_nth_match (PCRE_Type p, Int_Type nth)} + *\description + * The \var{pcre_nth_match} function returns an integer array whose values + * specify the locations of the beginning and end of the \var{nth} captured + * substrings of the most recent call to \var{pcre_exec} with the compiled + * pattern. A value of \var{nth} equal to 0 represents the substring + * representing the entire match of the pattern. + * + * If the \var{nth} match did not take place, the function returns \var{NULL}. + *\example + * After the execution of: + *#v+ + * str = "Error in file foo.c, line 127, column 10"; + * pattern = "file ([^,]+), line (\\d+)"; + * p = pcre_compile (pattern); + * if (pcre_exec (p, str)) + * { + * match_pos = pcre_nth_match (p, 0); + * file_pos = pcre_nth_match (p, 1); + * line_pos = pcre_nth_match (p, 2); + * } + *#v- + * \exmp{match_pos} will be set to \exmp{[9,29]}, \exmp{file_pos} to \exmp{[14,19,]} + * and \exmp{line_pos} to \exmp{[26,29]}. These integer arrays may be used to + * extract the substrings matched by the pattern, e.g., + *#v+ + * file = substr (str, file_pos[0]+1, file_pos[1]-file_pos[0]); + *#v- + * Alternatively, the function \var{pcre_nth_substr} may be used to get the + * matched substrings: + *#v+ + * file = pcre_nth_substr (p, str, 0); + *#v- + *\seealso{pcre_compile, pcre_exec, pcre_nth_substr} + *%- + */ + MAKE_INTRINSIC_3("pcre_nth_substr", _pcre_nth_substr, V, P, S, I), +/*%+ + *\function{pcre_nth_substr} + *\synopsis{Extract the nth substring from a PCRE match} + *\usage{String_Type pcre_nth_substr (PCRE_Type p, String_Type str, Int_Type nth)} + *\description + * This function may be used to extract the \var{nth} captured substring + * resulting from the most recent use of the compiled pattern \var{p} by the + * \var{pcre_exec} function. Unlike \var{pcre_nth_match}, this function returns + * the specified captured substring itself and not the position of the substring. + * For this reason, the subject string of the pattern is a required argument. + *\seealso{pcre_compile, pcre_exec, pcre_nth_match} + *%- + */ + MAKE_INTRINSIC_1("slang_to_pcre", slang_to_pcre, V, S), +/*%+ + *\function{slang_to_pcre} + *\synopsis{Convert a S-Lang regular expression to a PCRE one} + *\usage{String_Type slang_to_pcre (String_Type pattern)} + *\description + * This function may be used to convert a slang regular expression to a PCRE + * compatible one. The converted is returned. + *\seealso{pcre_compile, string_match} + *%- + */ + SLANG_END_INTRIN_FUN_TABLE +}; + +static SLang_IConstant_Type PCRE_Consts [] = +{ + /* compile options */ + MAKE_ICONSTANT("PCRE_ANCHORED", PCRE_ANCHORED), + MAKE_ICONSTANT("PCRE_CASELESS", PCRE_CASELESS), + MAKE_ICONSTANT("PCRE_DOLLAR_ENDONLY", PCRE_DOLLAR_ENDONLY), + MAKE_ICONSTANT("PCRE_DOTALL", PCRE_DOTALL), + MAKE_ICONSTANT("PCRE_EXTENDED", PCRE_EXTENDED), + MAKE_ICONSTANT("PCRE_EXTRA", PCRE_EXTRA), + MAKE_ICONSTANT("PCRE_MULTILINE", PCRE_MULTILINE), + MAKE_ICONSTANT("PCRE_UNGREEDY", PCRE_UNGREEDY), + MAKE_ICONSTANT("PCRE_UTF8", PCRE_UTF8), + + /* exec options */ + MAKE_ICONSTANT("PCRE_NOTBOL", PCRE_NOTBOL), + MAKE_ICONSTANT("PCRE_NOTEOL", PCRE_NOTEOL), + MAKE_ICONSTANT("PCRE_NOTEMPTY", PCRE_NOTEMPTY), + SLANG_END_ICONST_TABLE +}; + +#undef P +#undef I +#undef V +#undef S + +static void patchup_intrinsic_table (SLang_Intrin_Fun_Type *table, + unsigned char dummy, unsigned char type) +{ + while (table->name != NULL) + { + unsigned int i, nargs; + unsigned char *args; + + nargs = table->num_args; + args = table->arg_types; + for (i = 0; i < nargs; i++) + { + if (args[i] == dummy) + args[i] = type; + } + + /* For completeness */ + if (table->return_type == dummy) + table->return_type = type; + + table++; + } +} + + +static int register_pcre_type (void) +{ + SLang_Class_Type *cl; + + if (NULL == (cl = SLclass_allocate_class ("PCRE_Type"))) + return -1; + + if (-1 == SLclass_set_destroy_function (cl, destroy_pcre)) + return -1; + + /* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a + * type. + */ + if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, sizeof (PCRE_Type), SLANG_CLASS_TYPE_MMT)) + return -1; + + PCRE_Type_Id = SLclass_get_class_id (cl); + patchup_intrinsic_table (PCRE_Intrinsics, DUMMY_PCRE_TYPE, PCRE_Type_Id); + + return 0; +} + +static void *do_malloc (size_t n) +{ + return (void *) SLmalloc (n); +} + +static void do_free (void *x) +{ + SLfree ((char *) x); +} + +int init_pcre_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if (-1 == register_pcre_type ()) + return -1; + + pcre_malloc = do_malloc; + pcre_free = do_free; + + if ((-1 == SLns_add_intrin_fun_table (ns, PCRE_Intrinsics, "__PCRE__")) + || (-1 == SLns_add_iconstant_table (ns, PCRE_Consts, NULL))) + return -1; + + return 0; +} + + +/* This function is optional */ +void deinit_pcre_module (void) +{ +} + diff --git a/libslang/modules/select-module.c b/libslang/modules/select-module.c new file mode 100644 index 0000000..f085152 --- /dev/null +++ b/libslang/modules/select-module.c @@ -0,0 +1,238 @@ +/* Copyright (c) 2001 John E. Davis + * This file is part of the S-Lang library. + * + * You may distribute under the terms of either the GNU General Public + * License or the Perl Artistic License. + */ +#include <stdio.h> +#include <slang.h> + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +SLANG_MODULE(select); + +static int pop_fd_set (SLang_Array_Type **ats, + fd_set **fd_set_p, fd_set *fd_set_buf, + int *max_n) +{ + unsigned int num, i; + SLang_Array_Type *at; + SLFile_FD_Type **f; + + *ats = NULL; + *fd_set_p = NULL; + + if (SLang_peek_at_stack () == SLANG_NULL_TYPE) + return SLang_pop_null (); + + if (-1 == SLang_pop_array_of_type (&at, SLANG_FILE_FD_TYPE)) + return -1; + + FD_ZERO(fd_set_buf); + *fd_set_p = fd_set_buf; + + *ats = at; + num = at->num_elements; + f = (SLFile_FD_Type **) at->data; + + for (i = 0; i < num; i++) + { + int fd; + + if (-1 == SLfile_get_fd (f[i], &fd)) + continue; + + if (fd > *max_n) + *max_n = fd; + + FD_SET(fd, fd_set_buf); + } + + return 0; +} + +static SLang_Array_Type *do_fdisset (int nready, SLang_Array_Type *fds, fd_set *fdset) +{ + SLang_Array_Type *at; + unsigned int i, num; + SLFile_FD_Type **f; + + if (fds == NULL) + nready = 0; + + if (nready) + { + nready = 0; + num = fds->num_elements; + f = (SLFile_FD_Type **) fds->data; + for (i = 0; i < num; i++) + { + int fd; + + if (-1 == SLfile_get_fd (f[i], &fd)) + continue; + + if (FD_ISSET(fd, fdset)) + nready++; + } + } + + at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, &nready, 1); + if (at == NULL) + return NULL; + + if (nready) + { + int *indx = (int *) at->data; + f = (SLFile_FD_Type **) fds->data; + num = fds->num_elements; + for (i = 0; i < num; i++) + { + int fd; + + if (-1 == SLfile_get_fd (f[i], &fd)) + continue; + + if (FD_ISSET(fd, fdset)) + *indx++ = (int) i; + } + } + + return at; +} + +static int push_select_struct (int num, + SLang_Array_Type *at_read, + SLang_Array_Type *at_write, + SLang_Array_Type *at_except, + fd_set *readfs, fd_set *writefds, fd_set *exceptfds) +{ + char *field_names [4]; + unsigned char field_types[4]; + VOID_STAR field_values [4]; + SLang_Array_Type *iread, *iwrite, *iexcept; + + iread = iwrite = iexcept = NULL; + + field_names[0] = "nready"; + field_names[1] = "iread"; + field_names[2] = "iwrite"; + field_names[3] = "iexcept"; + field_types[0] = SLANG_INT_TYPE; + field_types[1] = SLANG_ARRAY_TYPE; + field_types[2] = SLANG_ARRAY_TYPE; + field_types[3] = SLANG_ARRAY_TYPE; + field_values[0] = # + + if ((NULL == (iread = do_fdisset (num, at_read, readfs))) + || (NULL == (iwrite = do_fdisset (num, at_write, writefds))) + || (NULL == (iexcept = do_fdisset (num, at_except, exceptfds)))) + { + SLang_free_array (iread); + SLang_free_array (iwrite); + return -1; + } + + field_values[1] = &iread; + field_values[2] = &iwrite; + field_values[3] = &iexcept; + + /* Note: This function call pushes the struct and frees it upon error. */ + return SLstruct_create_struct (4, field_names, field_types, field_values); +} + + +/* Usage: Struct_Type select (R[],W[],E[],TIME) */ + +static void select_intrin (double *secsp) +{ + SLang_Array_Type *at_read, *at_write, *at_except; + fd_set readfs_buf, writefds_buf, exceptfds_buf; + fd_set readfs_save_buf, writefds_save_buf, exceptfds_save_buf; + fd_set *readfs, *writefds, *exceptfds; + struct timeval tv, *tv_ptr; + double secs; + int ret, n; + + secs = *secsp; + if (secs < 0.0) tv_ptr = NULL; + else + { + tv.tv_sec = (unsigned long) secs; + tv.tv_usec = (unsigned long) ((secs - tv.tv_sec) * 1e6); + tv_ptr = &tv; + } + + n = 0; + if (-1 == pop_fd_set (&at_except, &exceptfds, &exceptfds_buf, &n)) + return; + if (-1 == pop_fd_set (&at_write, &writefds, &writefds_buf, &n)) + { + SLang_free_array (at_except); + return; + } + if (-1 == pop_fd_set (&at_read, &readfs, &readfs_buf, &n)) + goto free_return; + + readfs_save_buf = readfs_buf; + writefds_save_buf = writefds_buf; + exceptfds_save_buf = exceptfds_buf; + + n += 1; + while (-1 == (ret = select (n, readfs, writefds, exceptfds, tv_ptr))) + { +#ifdef EINTR + if (errno == EINTR) + { + readfs_buf = readfs_save_buf; + writefds_buf = writefds_save_buf; + exceptfds_buf = exceptfds_save_buf; + continue; + } +#endif + (void) SLerrno_set_errno (errno); + break; + } + + if (ret == -1) + (void) SLang_push_null (); + else + (void) push_select_struct (ret, at_read, at_write, at_except, + readfs, writefds, exceptfds); + + + free_return: + SLang_free_array (at_read); + SLang_free_array (at_write); + SLang_free_array (at_except); +} + +static SLang_Intrin_Fun_Type Select_Intrinsics [] = +{ + MAKE_INTRINSIC_1("select", select_intrin, SLANG_VOID_TYPE, SLANG_DOUBLE_TYPE), + SLANG_END_INTRIN_FUN_TABLE +}; + + +int init_select_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns; + + ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if (-1 == SLns_add_intrin_fun_table (ns, Select_Intrinsics, "__SELECT__")) + return -1; + + return 0; +} + +/* This function is optional */ +void deinit_select_module (void) +{ +} diff --git a/libslang/modules/smg-module.c b/libslang/modules/smg-module.c new file mode 100644 index 0000000..12a1d90 --- /dev/null +++ b/libslang/modules/smg-module.c @@ -0,0 +1,324 @@ +/* This module implements and interface to the SLang SMG routines */ +#include <stdio.h> +#include <slang.h> + +SLANG_MODULE(smg); + +/* If this is +1, the then it is ok to call the SLsmg routines. If it is + * 0, then only SLsmg_init_smg may be called. If it is -1, then SLsmg is + * suspended and one must call SLsmg_resume_smg. + */ + +static int Smg_Initialized; + +static void smg_write_to_status_line (char *s) +{ + if (Smg_Initialized <= 0) + return; + + (void) SLtt_write_to_status_line (s, 0); +} + + +static void smg_suspend_smg (void) +{ + if (Smg_Initialized <= 0) + return; + + (void) SLsmg_suspend_smg (); + Smg_Initialized = -1; +} + +static void smg_resume_smg (void) +{ + if (Smg_Initialized != -1) + return; + + (void) SLsmg_resume_smg (); + Smg_Initialized = 1; +} + +static void smg_erase_eol (void) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_erase_eol (); +} + +static void smg_gotorc (int *r, int *c) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_gotorc (*r, *c); +} + +static void smg_erase_eos (void) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_erase_eos (); +} + +static void smg_reverse_video (void) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_reverse_video (); +} + +static void smg_set_color (int *c) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_set_color (*c); +} + +static void smg_normal_video (void) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_normal_video (); +} + +static void smg_write_string (char *s) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_write_string (s); +} + +static void smg_write_nstring (char *s, int *len) +{ + if ((Smg_Initialized <= 0) + || (*len < 0)) + return; + + SLsmg_write_nstring (s, (unsigned int) *len); +} + +static void smg_write_wrapped_string (char *s, int *r, int *c, int *dr, int *dc, + int *fill) +{ + if (Smg_Initialized <= 0) + return; + + SLsmg_write_wrapped_string (s, *r, *c, *dr, *dc, *fill); +} + +static int smg_char_at (void) +{ + if (Smg_Initialized <= 0) return -1; + return (int) SLsmg_char_at (); +} + +static void smg_set_screen_start (int *rp, int *cp) +{ + int r, c; + + if (Smg_Initialized <= 0) return; + r = *rp; + c = *cp; + SLsmg_set_screen_start (&r, &c); +} + +static void smg_draw_hline (int *dn) +{ + if (Smg_Initialized <= 0) + return; + + SLsmg_draw_hline (*dn); +} + +static void smg_draw_vline (int *dn) +{ + if (Smg_Initialized <= 0) + return; + + SLsmg_draw_vline (*dn); +} + +static void smg_draw_object (int *r, int *c, int *obj) +{ + if (Smg_Initialized <= 0) return; + SLsmg_draw_object (*r, *c, *obj); +} + +static void smg_draw_box (int *r, int *c,int *dr, int *dc) +{ + if (Smg_Initialized <= 0) return; + SLsmg_draw_box (*r, *c, *dr, *dc); +} + +static int smg_get_column (void) +{ + if (Smg_Initialized <= 0) return -1; + return SLsmg_get_column(); +} + +static int smg_get_row (void) +{ + if (Smg_Initialized <= 0) return -1; + return SLsmg_get_row(); +} + +static void smg_forward (int *n) +{ + if (Smg_Initialized <= 0) return; + SLsmg_forward (*n); +} + +static void smg_set_color_in_region (int *color, int *r, int *c, int *dr, int *dc) +{ + if (Smg_Initialized <= 0) return; + SLsmg_set_color_in_region (*color, *r, *c, *dr, *dc); +} + + +static void smg_cls (void) +{ + if (Smg_Initialized <= 0) + return; + SLsmg_cls (); +} + +static void smg_refresh (void) +{ + if (Smg_Initialized <= 0) + return; + SLsig_block_signals (); + SLsmg_refresh (); + SLsig_unblock_signals (); +} + +static void smg_reset_smg (void) +{ + if (Smg_Initialized <= 0) + return; + SLsig_block_signals (); + SLsmg_reset_smg (); + SLsig_unblock_signals (); + Smg_Initialized = 0; +} + +static void smg_init_smg (void) +{ + if (Smg_Initialized != 0) + return; + SLsig_block_signals (); + (void) SLsmg_init_smg (); + SLsig_unblock_signals (); + Smg_Initialized = 1; +} + +static void smg_define_color (int *obj, char *fg, char *bg) +{ + SLtt_set_color (*obj, NULL, fg, bg); +} + +#define I SLANG_INT_TYPE +#define S SLANG_STRING_TYPE +static SLang_Intrin_Fun_Type Smg_Intrinsics [] = +{ + MAKE_INTRINSIC_0("smg_suspend_smg", smg_suspend_smg, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_resume_smg", smg_resume_smg, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_erase_eol", smg_erase_eol, SLANG_VOID_TYPE), + MAKE_INTRINSIC_II("smg_gotorc", smg_gotorc, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_erase_eos", smg_erase_eos, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_reverse_video", smg_reverse_video, SLANG_VOID_TYPE), + MAKE_INTRINSIC_I("smg_set_color", smg_set_color, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_normal_video", smg_normal_video, SLANG_VOID_TYPE), + MAKE_INTRINSIC_S("smg_write_string", smg_write_string, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_cls", smg_cls, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_refresh", smg_refresh, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_reset_smg", smg_reset_smg, SLANG_VOID_TYPE), + MAKE_INTRINSIC_0("smg_init_smg", smg_init_smg, SLANG_VOID_TYPE), + + MAKE_INTRINSIC_SI("smg_write_nstring", smg_write_nstring, SLANG_VOID_TYPE), + MAKE_INTRINSIC_6("smg_write_wrapped_string", smg_write_wrapped_string, SLANG_VOID_TYPE, S,I,I,I,I,I), + MAKE_INTRINSIC_0("smg_char_at", smg_char_at, SLANG_INT_TYPE), + MAKE_INTRINSIC_II("smg_set_screen_start", smg_set_screen_start, SLANG_VOID_TYPE), + MAKE_INTRINSIC_I("smg_draw_hline", smg_draw_hline, SLANG_VOID_TYPE), + MAKE_INTRINSIC_I("smg_draw_vline", smg_draw_vline, SLANG_VOID_TYPE), + MAKE_INTRINSIC_III("smg_draw_object", smg_draw_object, SLANG_VOID_TYPE), + MAKE_INTRINSIC_4("smg_draw_box", smg_draw_box, SLANG_VOID_TYPE,I,I,I,I), + MAKE_INTRINSIC_0("smg_get_column", smg_get_column, SLANG_INT_TYPE), + MAKE_INTRINSIC_0("smg_get_row", smg_get_row, SLANG_INT_TYPE), + MAKE_INTRINSIC_I("smg_forward", smg_forward, SLANG_VOID_TYPE), + MAKE_INTRINSIC_5("smg_set_color_in_region", smg_set_color_in_region, SLANG_VOID_TYPE, I, I, I, I, I), + + MAKE_INTRINSIC_ISS("smg_define_color", smg_define_color, SLANG_VOID_TYPE), + MAKE_INTRINSIC_S("smg_write_to_status_line", smg_write_to_status_line, SLANG_VOID_TYPE), + SLANG_END_INTRIN_FUN_TABLE +}; + +static SLang_Intrin_Var_Type Smg_Variables [] = +{ + MAKE_VARIABLE("Smg_Display_Eight_Bit", &SLsmg_Display_Eight_Bit, I, 0), + MAKE_VARIABLE("Smg_Tab_Width", &SLsmg_Tab_Width, I, 0), + MAKE_VARIABLE("Smg_Newline_Behavior", &SLsmg_Newline_Behavior, I, 0), + MAKE_VARIABLE("Smg_Backspace_Moves", &SLsmg_Backspace_Moves, I, 0), + MAKE_VARIABLE("Smg_Screen_Rows", &SLtt_Screen_Rows, I, 1), + MAKE_VARIABLE("Smg_Screen_Cols", &SLtt_Screen_Cols, I, 1), + SLANG_END_INTRIN_VAR_TABLE +}; + +static SLang_IConstant_Type Smg_Constants [] = +{ + MAKE_ICONSTANT("SMG_NEWLINE_IGNORED", SLSMG_NEWLINE_IGNORED), + MAKE_ICONSTANT("SMG_NEWLINE_MOVES", SLSMG_NEWLINE_MOVES), + MAKE_ICONSTANT("SMG_NEWLINE_SCROLLS", SLSMG_NEWLINE_SCROLLS), + MAKE_ICONSTANT("SMG_NEWLINE_PRINTABLE", SLSMG_NEWLINE_PRINTABLE), + + MAKE_ICONSTANT("SMG_HLINE_CHAR", SLSMG_HLINE_CHAR), + MAKE_ICONSTANT("SMG_VLINE_CHAR", SLSMG_VLINE_CHAR), + MAKE_ICONSTANT("SMG_ULCORN_CHAR", SLSMG_ULCORN_CHAR), + MAKE_ICONSTANT("SMG_URCORN_CHAR", SLSMG_URCORN_CHAR), + MAKE_ICONSTANT("SMG_LLCORN_CHAR", SLSMG_LLCORN_CHAR), + MAKE_ICONSTANT("SMG_LRCORN_CHAR", SLSMG_LRCORN_CHAR), + MAKE_ICONSTANT("SMG_CKBRD_CHAR", SLSMG_CKBRD_CHAR), + MAKE_ICONSTANT("SMG_RTEE_CHAR", SLSMG_RTEE_CHAR), + MAKE_ICONSTANT("SMG_LTEE_CHAR", SLSMG_LTEE_CHAR), + MAKE_ICONSTANT("SMG_UTEE_CHAR", SLSMG_UTEE_CHAR), + MAKE_ICONSTANT("SMG_DTEE_CHAR", SLSMG_DTEE_CHAR), + MAKE_ICONSTANT("SMG_PLUS_CHAR", SLSMG_PLUS_CHAR), + + SLANG_END_ICONST_TABLE +}; +#undef I +#undef S + +int init_smg_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if ((-1 == SLns_add_intrin_fun_table (ns, Smg_Intrinsics, "__SMG__")) + || (-1 == SLns_add_intrin_var_table (ns, Smg_Variables, NULL)) + || (-1 == SLns_add_iconstant_table (ns, Smg_Constants, NULL))) + return -1; + + SLtt_get_terminfo (); + Smg_Initialized = 0; + return 0; +} + +#if 0 +int init_smg_module (void) +{ + if ((-1 == SLadd_intrin_fun_table (Smg_Intrinsics, "__SMG__")) + || (-1 == SLadd_intrin_var_table (Smg_Variables, NULL)) + || (-1 == SLadd_iconstant_table (Smg_Constants, NULL))) + return -1; + + SLtt_get_terminfo (); + Smg_Initialized = 0; + return 0; +} +#endif + +/* This function is optional */ +void deinit_smg_module (void) +{ + smg_reset_smg (); +} diff --git a/libslang/modules/smg.sl b/libslang/modules/smg.sl new file mode 100644 index 0000000..80f9064 --- /dev/null +++ b/libslang/modules/smg.sl @@ -0,0 +1,70 @@ +import ("smg", "Global"); % Global namespace + +static variable Button_Color = 3; +static variable Box_Color = 2; +static variable Normal_Color = 1; + +smg_define_color (Button_Color, "white", "green"); +smg_define_color (Box_Color, "yellow", "blue"); +smg_define_color (Normal_Color, "green", "red"); + +static define display_button (name, r, c) +{ + smg_gotorc (r, c); + smg_set_color (Button_Color); + smg_write_string (" " + name + " "); + smg_set_color (Normal_Color); +} + +static define draw_centered_string (s, r, c, dc) +{ + variable len; + + len = strlen (s); + smg_gotorc (r, c + (dc - len)/2); + smg_write_string (s); +} + +static define get_yes_no_cancel (question) +{ + variable r, c, dr, dc; + + dc = strlen (question) + 5; + dr = 7; + + % We also need room for the yes-no-cancel buttons + if (dc < 32) dc = 36; + + r = (Smg_Screen_Rows - dr)/2; + c = (Smg_Screen_Cols - dc)/2; + + smg_set_color (Box_Color); + smg_draw_box (r, c, dr, dc); + smg_set_color (Normal_Color); + + r += 2; + + draw_centered_string (question + "?", r, c, dc); + + r += 2; + display_button ("Yes", r, c + 4); + display_button ("No", r, c + 14); + display_button ("Cancel", r, c + 24); +} + + +smg_write_to_status_line ("smg-module demo"); +smg_init_smg (); +smg_set_color(Normal_Color); +smg_erase_eos (); +get_yes_no_cancel ("This demo will exit in 5 seconds"); + + +smg_refresh (); +sleep (5); + +smg_write_to_status_line (""); + +%smg_reset_smg (); + +exit(0); diff --git a/libslang/modules/template.c b/libslang/modules/template.c new file mode 100644 index 0000000..b0b7d60 --- /dev/null +++ b/libslang/modules/template.c @@ -0,0 +1,49 @@ +#include <stdio.h> +#include <slang.h> + +SLANG_MODULE(<MODULE-NAME>); + +#define MODULE_MAJOR_VERSION 0 +#define MODULE_MINOR_VERSION 0 +#define MODULE_PATCH_LEVEL 0 +static char *Module_Version_String = "0.0.0"; +#define MODULE_VERSION_NUMBER \ + (MODULE_MAJOR_VERSION*10000+MODULE_MINOR_VERSION*100+MODULE_PATCH_LEVEL) + +/* Define intrinsics here */ + +static SLang_Intrin_Fun_Type Module_Intrinsics [] = +{ + SLANG_END_INTRIN_FUN_TABLE +}; + +static SLang_Intrin_Var_Type Module_Variables [] = +{ + MAKE_VARIABLE("_<MODULE-NAME>_module_version_string", &Module_Version_String, SLANG_STRING_TYPE, 1), + SLANG_END_INTRIN_VAR_TABLE +}; + +static SLang_IConstant_Type Module_Constants [] = +{ + MAKE_ICONSTANT("_<MODULE-NAME>_module_version", MODULE_VERSION_NUMBER), + SLANG_END_ICONST_TABLE +}; + +int init_<MODULE-NAME>_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if ((-1 == SLns_add_intrin_fun_table (ns, Module_Intrinsics, NULL)) + || (-1 == SLns_add_intrin_var_table (ns, Module_Variables, NULL)) + || (-1 == SLns_add_iconstant_table (ns, Module_Constants, NULL))) + return -1; + + return 0; +} + +/* This function is optional */ +void deinit_<MODULE-NAME>_module (void) +{ +} diff --git a/libslang/modules/termios-module.c b/libslang/modules/termios-module.c new file mode 100644 index 0000000..e853be9 --- /dev/null +++ b/libslang/modules/termios-module.c @@ -0,0 +1,440 @@ +/* Copyright (c) 2001 John E. Davis + * This file is part of the S-Lang library. + * + * You may distribute under the terms of either the GNU General Public + * License or the Perl Artistic License. + */ +#include <stdio.h> +#include <slang.h> + +#include <unistd.h> +#include <string.h> +#include <termios.h> +#include <errno.h> + +SLANG_MODULE(termios); + +static int Termios_Type_Id; + +static int check_and_set_errno (int e) +{ +#ifdef EINTR + if (e == EINTR) + return 0; +#endif + (void) SLerrno_set_errno (e); + return -1; +} + +static int do_syscall_0 (int (*fun)(int), SLFile_FD_Type *f) +{ + int fd; + int ret; + + if (-1 == SLfile_get_fd (f, &fd)) + return -1; + + while ((-1 == (ret = (*fun) (fd))) + && (0 == check_and_set_errno (errno))) + ; + + return ret; +} + +static int do_syscall_1 (int (*fun)(int, int), SLFile_FD_Type *f, int arg) +{ + int fd; + int ret; + + if (-1 == SLfile_get_fd (f, &fd)) + return -1; + + while ((-1 == (ret = (*fun) (fd, arg))) + && (0 == check_and_set_errno (errno))) + ; + + return ret; +} + +static int do_syscall_struct_1 (int (*fun)(int, void *), SLFile_FD_Type *f, void *v) +{ + int fd; + int ret; + + if (-1 == SLfile_get_fd (f, &fd)) + return -1; + + while ((-1 == (ret = (*fun) (fd, v))) + && (0 == check_and_set_errno (errno))) + ; + + return ret; +} + +static int do_syscall_struct_2 (int (*fun)(int, int, void *), SLFile_FD_Type *f, int i, void *v) +{ + int fd; + int ret; + + if (-1 == SLfile_get_fd (f, &fd)) + return -1; + + while ((-1 == (ret = (*fun) (fd, i, v))) + && (0 == check_and_set_errno (errno))) + ; + + return ret; +} + +#define DO_SYSCALL_0(fun, f) do_syscall_0((int(*)(int))(fun),(f)) +#define DO_SYSCALL_1(fun, f, i) do_syscall_1((int(*)(int,int))(fun),(f),(i)) +#define DO_SYSCALL_STRUCT_1(fun, f, s) \ + do_syscall_struct_1((int(*)(int, void*))(fun), (f), (void*)(s)) +#define DO_SYSCALL_STRUCT_2(fun, f, i, s) \ + do_syscall_struct_2((int(*)(int, int, void*))(fun), (f), (i), (void*)(s)) + + +static int tcdrain_intrin (SLFile_FD_Type *f) +{ + return DO_SYSCALL_0 (tcdrain, f); +} + +static int tcflow_intrin (SLFile_FD_Type *f, int *action) +{ + return DO_SYSCALL_1 (tcflow, f, *action); +} + +static int tcflush_intrin (SLFile_FD_Type *f, int *action) +{ + return DO_SYSCALL_1 (tcflush, f, *action); +} + +static int tcgetpgrp_intrin (SLFile_FD_Type *f) +{ + return DO_SYSCALL_0 (tcgetpgrp, f); +} + +static int tcsetpgrp_intrin (SLFile_FD_Type *f, int *id) +{ + return DO_SYSCALL_1 (tcgetpgrp, f, *id); +} + +static int tcsendbreak_intrin (SLFile_FD_Type *f, int *action) +{ + return DO_SYSCALL_1 (tcsendbreak, f, *action); +} + +static void destroy_termios (unsigned char type, VOID_STAR f) +{ + (void) type; + SLfree ((char *) f); +} + +static SLang_MMT_Type *allocate_termios (struct termios *s) +{ + struct termios *s1; + SLang_MMT_Type *mmt; + + s1 = (struct termios *) SLmalloc (sizeof (struct termios)); + if (s1 == NULL) + return NULL; + + memcpy (s1, s, sizeof (struct termios)); + if (NULL == (mmt = SLang_create_mmt (Termios_Type_Id, (VOID_STAR) s1))) + SLfree ((char *) s1); + return mmt; +} + +static void tcgetattr_intrin (SLFile_FD_Type *f) +{ + struct termios s; + SLang_MMT_Type *mmt; + + if (-1 == DO_SYSCALL_STRUCT_1(tcgetattr,f,&s)) + { + SLang_push_null (); + return; + } + + mmt = allocate_termios (&s); /* NULL ok */ + if (-1 == SLang_push_mmt (mmt)) + SLang_free_mmt (mmt); +} + +static int tcsetattr_intrin (SLFile_FD_Type *f, int *when, struct termios *s) +{ + return DO_SYSCALL_STRUCT_2(tcsetattr,f,*when,s); +} + +static int termios_get_oflag (struct termios *s) +{ + return s->c_oflag; +} +static int termios_get_iflag (struct termios *s) +{ + return s->c_iflag; +} +static int termios_get_cflag (struct termios *s) +{ + return s->c_cflag; +} +static int termios_get_lflag (struct termios *s) +{ + return s->c_lflag; +} + +static void termios_get_cc (struct termios *s) +{ + SLang_Array_Type *at; + int dims = NCCS; + int i; + unsigned char *at_data; + + at = SLang_create_array (SLANG_UCHAR_TYPE, 0, NULL, &dims, 1); + if (at == NULL) + return; + at_data = (unsigned char *) at->data; + + for (i = 0; i < NCCS; i++) + at_data[i] = (unsigned char) s->c_cc[i]; + + (void) SLang_push_array (at, 1); +} + + +static void termios_set_oflag (struct termios *s, int *flag) +{ + s->c_oflag = *flag; +} +static void termios_set_iflag (struct termios *s, int *flag) +{ + s->c_iflag = *flag; +} +static void termios_set_cflag (struct termios *s, int *flag) +{ + s->c_cflag = *flag; +} +static void termios_set_lflag (struct termios *s, int *flag) +{ + s->c_lflag = *flag; +} + +static void termios_set_cc (void) +{ + SLang_Array_Type *at; + SLang_MMT_Type *mmt; + struct termios *s; + unsigned char *at_data; + int i; + + if (-1 == SLang_pop_array_of_type (&at, SLANG_UCHAR_TYPE)) + return; + if (NULL == (mmt = SLang_pop_mmt (Termios_Type_Id))) + goto free_and_return; + + s = SLang_object_from_mmt (mmt); + if (at->num_elements != NCCS) + { + SLang_verror (SL_TYPE_MISMATCH, + "Expecting UChar_Type[%d]", NCCS); + goto free_and_return; + } + + at_data = (unsigned char *) at->data; + for (i = 0; i < NCCS; i++) + s->c_cc[i] = at_data[i]; + + /* drop */ + + free_and_return: + SLang_free_array (at); + SLang_free_mmt (mmt); +} + + +static int termios_dereference (unsigned char type, VOID_STAR addr) +{ + struct termios *s; + SLang_MMT_Type *mmt; + + (void) type; + mmt = *(SLang_MMT_Type **) addr; + if (NULL == (s = SLang_object_from_mmt (mmt))) + return -1; + + mmt = allocate_termios (s); + if (-1 == SLang_push_mmt (mmt)) + { + SLang_free_mmt (mmt); + return -1; + } + + return 0; +} + + +#define DUMMY_TERMIOS_TYPE 255 +#define T DUMMY_TERMIOS_TYPE +#define F SLANG_FILE_FD_TYPE +#define I SLANG_INT_TYPE +#define V SLANG_VOID_TYPE +static SLang_Intrin_Fun_Type Termios_Intrinsics [] = +{ + MAKE_INTRINSIC_1("tcdrain", tcdrain_intrin, I, F), + MAKE_INTRINSIC_2("tcflow", tcflow_intrin, I, F, I), + MAKE_INTRINSIC_2("tcflush", tcflush_intrin, I, F, I), + MAKE_INTRINSIC_1("tcgetpgrp", tcgetpgrp_intrin, I, F), + MAKE_INTRINSIC_2("tcsetpgrp", tcsetpgrp_intrin, I, F, I), + MAKE_INTRINSIC_2("tcsendbreak", tcsendbreak_intrin, I, F, I), + MAKE_INTRINSIC_1("tcgetattr", tcgetattr_intrin, V, F), + MAKE_INTRINSIC_3("tcsetattr", tcsetattr_intrin, I, F, I, T), + MAKE_INTRINSIC_1("termios_get_oflag", termios_get_oflag, I, T), + MAKE_INTRINSIC_1("termios_get_iflag", termios_get_iflag, I, T), + MAKE_INTRINSIC_1("termios_get_cflag", termios_get_cflag, I, T), + MAKE_INTRINSIC_1("termios_get_lflag", termios_get_lflag, I, T), + MAKE_INTRINSIC_1("termios_get_cc", termios_get_cc, V, T), + MAKE_INTRINSIC_2("termios_set_oflag", termios_set_oflag, V, T, I), + MAKE_INTRINSIC_2("termios_set_iflag", termios_set_iflag, V, T, I), + MAKE_INTRINSIC_2("termios_set_cflag", termios_set_cflag, V, T, I), + MAKE_INTRINSIC_2("termios_set_lflag", termios_set_lflag, V, T, I), + MAKE_INTRINSIC_0("termios_set_cc", termios_set_cc, V), + + SLANG_END_INTRIN_FUN_TABLE +}; +#undef T +#undef I +#undef F +#undef V + +static SLang_IConstant_Type Termios_Consts [] = +{ + MAKE_ICONSTANT("TCOOFF", TCOOFF), + MAKE_ICONSTANT("TCOON", TCOON), + MAKE_ICONSTANT("TCIOFF", TCIOFF), + MAKE_ICONSTANT("TCION", TCION), + MAKE_ICONSTANT("TCIFLUSH", TCIFLUSH), + MAKE_ICONSTANT("TCOFLUSH", TCOFLUSH), + MAKE_ICONSTANT("TCIOFLUSH", TCIOFLUSH), + MAKE_ICONSTANT("TCSANOW", TCSANOW), + MAKE_ICONSTANT("TCSADRAIN", TCSADRAIN), + MAKE_ICONSTANT("TCSAFLUSH", TCSAFLUSH), + MAKE_ICONSTANT("BRKINT", BRKINT), + MAKE_ICONSTANT("IGNBRK", IGNBRK), + MAKE_ICONSTANT("IGNPAR", IGNPAR), + MAKE_ICONSTANT("PARMRK", PARMRK), + MAKE_ICONSTANT("INPCK", INPCK), + MAKE_ICONSTANT("ISTRIP", ISTRIP), + MAKE_ICONSTANT("INLCR", INLCR), + MAKE_ICONSTANT("IGNCR", IGNCR), + MAKE_ICONSTANT("ICRNL", ICRNL), + MAKE_ICONSTANT("IXON", IXON), + MAKE_ICONSTANT("IXOFF", IXOFF), + MAKE_ICONSTANT("CLOCAL", CLOCAL), + MAKE_ICONSTANT("CREAD", CREAD), + MAKE_ICONSTANT("CSIZE", CSIZE), + MAKE_ICONSTANT("CSTOPB", CSTOPB), + MAKE_ICONSTANT("HUPCL", HUPCL), + MAKE_ICONSTANT("PARENB", PARENB), + MAKE_ICONSTANT("PARODD", PARODD), + MAKE_ICONSTANT("ECHO", ECHO), + MAKE_ICONSTANT("ECHOE", ECHOE), + MAKE_ICONSTANT("ECHOK", ECHOK), + MAKE_ICONSTANT("ECHONL", ECHONL), + MAKE_ICONSTANT("ICANON", ICANON), + MAKE_ICONSTANT("ISIG", ISIG), + MAKE_ICONSTANT("NOFLSH", NOFLSH), + MAKE_ICONSTANT("TOSTOP", TOSTOP), + MAKE_ICONSTANT("IEXTEN", IEXTEN), + MAKE_ICONSTANT("VEOF", VEOF), + MAKE_ICONSTANT("VEOL", VEOL), + MAKE_ICONSTANT("VERASE", VERASE), + MAKE_ICONSTANT("VINTR", VINTR), + MAKE_ICONSTANT("VKILL", VKILL), + MAKE_ICONSTANT("VQUIT", VQUIT), + MAKE_ICONSTANT("VSUSP", VSUSP), + MAKE_ICONSTANT("VSTART", VSTART), + MAKE_ICONSTANT("VSTOP", VSTOP), +#ifdef ultrix /* Ultrix gets _POSIX_VDISABLE wrong! */ +# define NULL_VALUE -1 +#else +# ifdef _POSIX_VDISABLE +# define NULL_VALUE _POSIX_VDISABLE +# else +# define NULL_VALUE 255 +# endif +#endif + MAKE_ICONSTANT("VDISABLE", NULL_VALUE), + + SLANG_END_ICONST_TABLE +}; + +static void patchup_intrinsic_table (SLang_Intrin_Fun_Type *table, + unsigned char dummy, unsigned char type) +{ + while (table->name != NULL) + { + unsigned int i, nargs; + unsigned char *args; + + nargs = table->num_args; + args = table->arg_types; + for (i = 0; i < nargs; i++) + { + if (args[i] == dummy) + args[i] = type; + } + + /* For completeness */ + if (table->return_type == dummy) + table->return_type = type; + + table++; + } +} + + +static int register_termios_type (void) +{ + SLang_Class_Type *cl; + + if (NULL == (cl = SLclass_allocate_class ("Termios_Type"))) + return -1; + + if (-1 == SLclass_set_destroy_function (cl, destroy_termios)) + return -1; + cl->cl_dereference = termios_dereference; + + /* By registering as SLANG_VOID_TYPE, slang will dynamically allocate a + * type. + */ + if (-1 == SLclass_register_class (cl, SLANG_VOID_TYPE, sizeof (struct termios), SLANG_CLASS_TYPE_MMT)) + return -1; + + Termios_Type_Id = SLclass_get_class_id (cl); + patchup_intrinsic_table (Termios_Intrinsics, DUMMY_TERMIOS_TYPE, Termios_Type_Id); + + return 0; +} + +int init_termios_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns; + + ns = SLns_create_namespace (ns_name); + if (ns == NULL) + return -1; + + if (-1 == register_termios_type ()) + return -1; + + if ((-1 == SLns_add_intrin_fun_table (ns, Termios_Intrinsics, "__TERMIOS__")) + || (-1 == SLns_add_iconstant_table (ns, Termios_Consts, NULL))) + return -1; + + return 0; +} + +/* This function is optional */ +void deinit_termios_module (void) +{ +} diff --git a/libslang/modules/varray-module.c b/libslang/modules/varray-module.c new file mode 100644 index 0000000..d9caf3a --- /dev/null +++ b/libslang/modules/varray-module.c @@ -0,0 +1,224 @@ +#include <stdio.h> +#include <string.h> +#include <slang.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#ifndef MAP_FAILED +# define MAP_FAILED -1 +#endif + +SLANG_MODULE(varray); + +typedef struct +{ + unsigned long size_mmapped; + VOID_STAR addr; + VOID_STAR data; +} +MMap_Type; + +static void free_mmap_type (MMap_Type *m) +{ + if (m == NULL) + return; + if (m->addr != NULL) + (void) munmap ((char *) m->addr, m->size_mmapped); + SLfree ((char *)m); +} + +static void unmmap_array (SLang_Array_Type *at) +{ + if (at->client_data != NULL) + free_mmap_type ((MMap_Type *) at->client_data); + + at->data = NULL; + at->client_data = NULL; +} + + +static MMap_Type *mmap_file (char *file, unsigned int offset, + unsigned long num_bytes) +{ + FILE *fp; + int fd; + struct stat st; + VOID_STAR addr; + MMap_Type *m; + + fp = fopen (file, "rb"); + if (fp == NULL) + { + SLang_verror (SL_OBJ_NOPEN, "mmap_array: unable to open %s for reading", file); + return NULL; + } + fd = fileno (fp); + + if (-1 == fstat (fd, &st)) + { + SLang_verror (SL_INTRINSIC_ERROR, "mmap_array: stat %s failed", file); + fclose (fp); + return NULL; + } + + if (NULL == (m = (MMap_Type *) SLmalloc (sizeof (MMap_Type)))) + { + fclose (fp); + return NULL; + } + + m->size_mmapped = num_bytes + offset; + addr = (VOID_STAR)mmap (NULL, m->size_mmapped, PROT_READ, MAP_SHARED, fd, 0); + if (addr == (VOID_STAR)MAP_FAILED) + { + SLang_verror (SL_INTRINSIC_ERROR, "mmap_array: mmap %s failed", file); + SLfree ((char *) m); + fclose (fp); + return NULL; + } + m->addr = addr; + m->data = (VOID_STAR) ((char *)addr + offset); + + fclose (fp); + + return m; +} + +/* usage: + * a = mmap_array (file, offset, type, [dims]); + */ +static void mmap_array (void) +{ + SLang_Array_Type *a, *a_dims; + char *file; + unsigned char type; + int *dims; + unsigned int num_dims; + unsigned int i; + unsigned int num_elements; + unsigned int offset; + unsigned int sizeof_type; + unsigned long num_bytes; + MMap_Type *m; + VOID_STAR data; + + a_dims = NULL; + file = NULL; + data = NULL; + + if (-1 == SLang_pop_array_of_type (&a_dims, SLANG_INT_TYPE)) + return; + + num_dims = a_dims->num_elements; + dims = (int *)a_dims->data; + + if (-1 == SLang_pop_datatype (&type)) + goto return_error; + + switch (type) + { + case SLANG_CHAR_TYPE: + case SLANG_UCHAR_TYPE: + sizeof_type = 1; + break; + + case SLANG_SHORT_TYPE: + case SLANG_USHORT_TYPE: + sizeof_type = sizeof(short); + break; + + case SLANG_INT_TYPE: + case SLANG_UINT_TYPE: + sizeof_type = sizeof (int); + break; + + case SLANG_LONG_TYPE: + case SLANG_ULONG_TYPE: + sizeof_type = sizeof (long); + break; + + case SLANG_FLOAT_TYPE: + sizeof_type = sizeof (float); + break; + + case SLANG_DOUBLE_TYPE: + sizeof_type = sizeof (double); + break; + + case SLANG_COMPLEX_TYPE: + sizeof_type = 2 * sizeof (double); + break; + + default: + SLang_verror (SL_NOT_IMPLEMENTED, "mmap_array: unsupported data type"); + goto return_error; + } + + num_elements = 1; + for (i = 0; i < num_dims; i++) + { + if (dims[i] < 0) + { + SLang_verror (SL_USER_ERROR, "mmap_array: dims array must be positive"); + goto return_error; + } + + num_elements *= dims[i]; + } + if (num_dims == 0) + num_elements = 0; + + num_bytes = (unsigned long) sizeof_type * (unsigned long) num_elements; + + if (-1 == SLang_pop_uinteger (&offset)) + goto return_error; + + if (-1 == SLang_pop_slstring (&file)) + goto return_error; + + if (NULL == (m = mmap_file (file, offset, num_bytes))) + goto return_error; + + if (NULL == (a = SLang_create_array (type, 1, m->data, dims, num_dims))) + goto return_error; + + a->free_fun = unmmap_array; + a->client_data = (VOID_STAR) m; + + m = NULL; /* done with this */ + + (void) SLang_push_array (a, 1); + + /* drop */ + + return_error: + if (m != NULL) + free_mmap_type (m); + if (a_dims != NULL) + SLang_free_array (a_dims); + if (file != NULL) + SLang_free_slstring (file); +} + +static SLang_Intrin_Fun_Type Module_Intrinsics [] = +{ + MAKE_INTRINSIC_0("mmap_array", mmap_array, SLANG_VOID_TYPE), + SLANG_END_INTRIN_FUN_TABLE +}; + + +int init_varray_module_ns (char *ns_name) +{ + SLang_NameSpace_Type *ns; + + if (NULL == (ns = SLns_create_namespace (ns_name))) + return -1; + + if (-1 == SLns_add_intrin_fun_table (ns, Module_Intrinsics, NULL)) + return -1; + + return 0; +} + diff --git a/libslang/modules/varray.sl b/libslang/modules/varray.sl new file mode 100644 index 0000000..8b78558 --- /dev/null +++ b/libslang/modules/varray.sl @@ -0,0 +1,37 @@ +% This file shows how to use the varray-module to treat a file as an +% array of objects. +import ("varray"); + +% First of all, create an array of doubles +static variable x = [1:1000.0:1.0]; + +% and write it to disk +static variable file = "varray_example.dat"; +static variable fp = fopen (file, "wb"); +if (fp == NULL) +{ + () = fprintf (stderr, "failed to open %s\n", file); + exit (1); +} +if ((-1 == fwrite (x, fp)) + or (-1 == fclose (fp))) +{ + () = fprintf (stderr, "Failed to write x\n"); + exit (1); +} + +% Now associate an array with the file +variable y = mmap_array (file, 0, _typeof(x), length(x)); + +if (length (where (y != x))) +{ + fprintf (stderr, "mmap_array has failed\n"); + exit (1); +} + +y = 0; % remove the map + +exit (0); + + + |