diff options
Diffstat (limited to 'libslang/modules/termios-module.c')
-rw-r--r-- | libslang/modules/termios-module.c | 440 |
1 files changed, 440 insertions, 0 deletions
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) +{ +} |