Enclosed are some user-contributed SIOD enhancements and patches which I have been unfortunately too busy to include and integrate. You'll probably have noticed that in the past few years I've added little to SIOD besides operating-system-related support. These are in the form of email messages and include good work in two rather important practical areas, objects and string/character/array support. I'll dig up another email message that includes other IEEE/Revised-Report compatibility support. -George J. Carrette From mike@sepia.com Thu Jul 3 07:26:53 1997 Received: from netcom.netc.net by world.std.com (5.65c/Spike-2.0) id AA27711; Thu, 3 Jul 1997 03:27:17 -0400 Received: from mike (port154.netc.net [205.205.40.154]) by netcom.netc.net (8.8.5/8.8.5) with SMTP id DAA23806 for ; Thu, 3 Jul 1997 03:27:38 -0400 (EDT) Message-Id: <3.0.1.32.19970703032653.00960150@netc.net> X-Sender: mike@netc.net X-Mailer: Windows Eudora Pro Version 3.0.1 (32) Date: Thu, 03 Jul 1997 03:26:53 -0400 To: gjc@world.std.com From: Mike Schmidt Subject: SIOD Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Status: R Hi, Due to some requirements of our own, we have implemented into the very latest version of SIOD (3.5) a mechanism whereby we can overload some of the SIOD functions in order to use our own user-defined data types. For example, if we have a data type X, we can overload + so that we can do (+ X X) without interfering with the default routines. This has been implemented in such a way that only 1 line has been added to slib.c, all the rest is in a separate module. It's entirely compatible with the current version of SIOD and doesn't change the apparent behaviour of anything. The overloading is based on the types of the arguments passed. There is one restriction - it only works when there's at least one argument. It works like this: a new function init_ssubr() is defined, very similar to init_subr(). When init_ssubr() is called, it checks to see if the requested name is already defined. If not, it's the same as init_subr(). If the name is already defined, it changes the name of the existing function to something like x_1(), and adds the new function as x_2(). The original x() is then replaced by a lisp function that iterates over x_2(), then x_1(). When it evals x_2(), it expects either a normal return, in which case we're done, or a specific condition, which causes it to try the next function, in this case x_1(). In the attached dll, these overloaded functions are implemented just the same way as usual, except that they check the types of their arguments, and return as the result try_next() if the check fails. As long as the argument types are different, we can always call the right function. This is not the best way of implementing overloading, but it does work, and it works without having to change anything (except init_subrs_1(), to load the iterator). I don't know if this is interesting to you, but if it is, I'm willing to send you what we've done. I've deliberately kept it separate from your code so that we can port it instantly to any further versions of SIOD, or so that it can be easily removed. Or did you have another idea in mind for this purpose? By the way, in the latest version you added a bunch of __stdcall attributes for windows NT. What is the reasoning behind your choice of where you put stdcall, and where you left the default (__cdecl)? I'd like to be able to follow your example. I'm running uner NT 4.0, with VC++ 5.0. I did create the proper workspace and project definitions, which you are also welcome to, if you like. Sadly, a .mak file is no longer sufficient in 5.0 when using workspaces. Thanks for SIOD. We like it alot. Mike _______________________________________ Mike Schmidt Technologies SEPIA, Inc. Mike@sepia.com -or- SchmidtM@sepia.com www.sepia.com & vguide.sepia.com From mike@sepia.com Thu Jul 10 06:06:54 1997 Received: from netcom.netc.net by world.std.com (5.65c/Spike-2.0) id AA10535; Thu, 10 Jul 1997 02:07:33 -0400 Received: from mike (port177.netc.net [205.205.40.177]) by netcom.netc.net (8.8.5/8.8.5) with SMTP id CAA25992 for ; Thu, 10 Jul 1997 02:07:34 -0400 (EDT) Message-Id: <3.0.1.32.19970710020654.00976210@netc.net> X-Sender: mike@netc.net X-Mailer: Windows Eudora Pro Version 3.0.1 (32) Date: Thu, 10 Jul 1997 02:06:54 -0400 To: george j carrette From: Mike Schmidt Subject: SIOD Overloading Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=====================_868529214==_" Status: R --=====================_868529214==_ Content-Type: text/plain; charset="us-ascii" Hi, Here's the overloading code, finally. In running the sample program on Sunday, I discovered a problem that had to be fixed before sending it on. But here it is finally. If you do decide to implement this, I'm sure you'll improve it immensely. I've attached siod2.tar.gz to this message. It contains the following: sample2.c: sample program based on sample.c. Compile this with #define SIODX to enable the overloading functions. siod2.h: include file which is included automatically by siod.h if SIODX is defined. slib2.c: the code that implements the overloading. siod.h: made change to include siod2.h if SIODX is defined. slib.c: made two changes; one to init_storage() and another to init_subrs_1(). libsiod.def: added definitions for all functions exported from slib2.c There wouldn't be any problem just throwing siod2.h into siod.h, and the same for slib2.c and slib.c. I just kept them separate so that they can be easily ported to further versions of SIOD. Mike --=====================_868529214==_ Content-Type: application/octet-stream; name="siod2.tar.gz"; x-mac-type="477A6970"; x-mac-creator="477A6970" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="siod2.tar.gz" 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 u8/d5+5z97n7/Kc+/wcwKkmiALgBAA== --=====================_868529214==_ Content-Type: text/plain; charset="us-ascii" _______________________________________ Mike Schmidt Technologies SEPIA, Inc. Mike@sepia.com -or- SchmidtM@sepia.com www.sepia.com & vguide.sepia.com --=====================_868529214==_-- From mike@olan.com Wed Jul 2 21:16:02 1997 Received: from mail.NetVision.net.il by world.std.com (5.65c/Spike-2.0) id AA20186; Wed, 2 Jul 1997 17:31:28 -0400 Received: from alucard (cmm@ts047p10.pop3b.netvision.net.il [199.203.203.102]) by mail.netvision.net.il (8.8.5/8.8.5) with ESMTP id AAA09240 for gjc@world.std.com; Thu, 3 Jul 1997 00:16:02 +0300 (IDT) Date: Thu, 3 Jul 1997 00:16:02 +0300 (IDT) From: mike@olan.com Message-Id: <199707022116.AAA09240@mail.netvision.net.il> Subject: A patch to SIOD 3.4 to make it more compliant. Reply-To: mike@olan.com Apparently-To: Status: R Here goes the patch. It does the following: 1. Adds a char primitive type, char read/print syntax and all the char procedures required by R4RS. 2. Adds all the vector procedures required by R4RS. 3. Adds the missing string procedures. 4. Changes all SIOD string handling to be independent of whether there are null characters in arguments. Does it break anything? Thanks, cmm From mike@olan.com Sat Jul 5 12:16:28 1997 Received: from mail.NetVision.net.il by world.std.com (5.65c/Spike-2.0) id AA11359; Sat, 5 Jul 1997 08:18:53 -0400 Received: from olan.com (cmm@ts041p5.pop3b.netvision.net.il [199.203.202.241]) by mail.netvision.net.il (8.8.5/8.8.5) with SMTP id PAA01493 for gjc@world.std.com; Sat, 5 Jul 1997 15:16:28 +0300 (IDT) Date: Sat, 5 Jul 1997 15:16:28 +0300 (IDT) From: mike@olan.com Message-Id: <199707051216.PAA01493@mail.netvision.net.il> Subject: fixed patch for SIOD 3.4 Reply-To: mike@olan.com Apparently-To: Status: R Hi! I fixed some bugs in the previous patch and cleaned it up somewhat. No, it won't give you ports. It's just strings, chars, vectors and fixes to your string code (where it was sensitive to null chars in the middle of a scheme string). Thanks, cmm. diff -uu -b siod/siod.h siod.cmm/siod.h --- siod/siod.h Fri May 16 03:58:54 1997 +++ siod.cmm/siod.h Sat Jul 5 13:00:54 1997 @@ -16,6 +16,9 @@ struct {double data;} flonum; struct {char *pname; struct obj * vcell;} symbol; + /* added by cmm */ + struct {char chr;} chr; + /* -- */ struct {char *name; struct obj * (*f)(void);} subr0; struct {char *name; @@ -64,6 +67,9 @@ #define SUBRM(x) (*((*x).storage_as.subrm.f)) #define SUBRF(x) (*((*x).storage_as.subr.f)) #define FLONM(x) ((*x).storage_as.flonum.data) +/* added by cmm */ +#define CHR(x) ((*x).storage_as.chr.chr) +/* -- */ #define NIL ((struct obj *) 0) #define EQ(x,y) ((x) == (y)) @@ -98,6 +104,9 @@ #define tc_subr_4 19 #define tc_subr_5 20 #define tc_subr_2n 21 +/* added by cmm */ +#define tc_char 22 +/* -- */ #define FO_comment 35 #define tc_user_min 50 #define tc_user_max 100 @@ -120,6 +129,11 @@ #define NFLONUMP(x) NTYPEP(x,tc_flonum) #define NSYMBOLP(x) NTYPEP(x,tc_symbol) +/* added by cmm */ +#define CHARP(x) TYPEP(x, tc_char) +#define NCHARP(x) NTYPEP(x, tc_char) +/* -- */ + #define TKBUFFERN 5120 #ifndef WIN32 @@ -167,6 +181,9 @@ char *try_get_c_string(LISP x); long get_c_long(LISP x); double get_c_double(LISP x); +/* added by cmm */ +char get_c_char(LISP x); +/* -- */ LISP lerr(LISP message, LISP x); LISP newcell(long type); @@ -309,6 +326,62 @@ FILE *get_c_file(LISP p,FILE *deflt); char *last_c_errmsg(int); LISP llast_c_errmsg(int); + +/* added by cmm */ +LISP chrcons(char); +LISP is_char(LISP); +LISP char_eq(LISP, LISP); +LISP char_lt(LISP, LISP); +LISP char_gt(LISP, LISP); +LISP char_le(LISP, LISP); +LISP char_ge(LISP, LISP); +LISP char_ci_eq(LISP, LISP); +LISP char_ci_lt(LISP, LISP); +LISP char_ci_gt(LISP, LISP); +LISP char_ci_le(LISP, LISP); +LISP char_ci_ge(LISP, LISP); + +LISP is_char_alph(LISP); +LISP is_char_num(LISP); +LISP is_char_ws(LISP); +LISP is_char_upper(LISP); +LISP is_char_lower(LISP); +LISP char_to_int(LISP); +LISP int_to_char(LISP); +LISP char_upcase(LISP); +LISP char_downcase(LISP); + +LISP make_string(LISP, LISP); +LISP string(LISP); +LISP string_ref(LISP, LISP); +LISP string_set(LISP, LISP, LISP); +LISP string_eq(LISP, LISP); +LISP string_lt(LISP, LISP); +LISP string_gt(LISP, LISP); +LISP string_le(LISP, LISP); +LISP string_ge(LISP, LISP); +LISP string_ci_eq(LISP, LISP); +LISP string_ci_lt(LISP, LISP); +LISP string_ci_gt(LISP, LISP); +LISP string_ci_le(LISP, LISP); +LISP string_ci_ge(LISP, LISP); +LISP string_to_list(LISP); +LISP string_copy(LISP); +LISP string_fill(LISP, LISP); + +#define STRDATA(x) ((*x).storage_as.string.data) +#define STRDIM(x) ((*x).storage_as.string.dim) + +LISP make_vector(LISP, LISP); +LISP vector(LISP); +LISP vector_ref(LISP, LISP); +LISP vector_set(LISP, LISP, LISP); +LISP is_vector(LISP); +LISP vector_to_list(LISP); +LISP vector_copy(LISP); +LISP vector_fill(LISP, LISP); + +/* -- */ #define SAFE_STRCPY(_to,_from) safe_strcpy((_to),sizeof(_to),(_from)) #define SAFE_STRCAT(_to,_from) safe_strcat((_to),sizeof(_to),(_from)) diff -uu -b siod/slib.c siod.cmm/slib.c --- siod/slib.c Fri May 16 10:23:50 1997 +++ siod.cmm/slib.c Sat Jul 5 14:25:28 1997 @@ -1967,6 +1967,28 @@ case tc_symbol: gput_st(f,PNAME(exp)); break; +/* added by cmm */ + case tc_char: + { + char c = CHR(exp); + switch (c) { + case ' ': + sprintf(tkbuffer, "#\\space"); + break; + case '\n': + sprintf(tkbuffer, "#\\newline"); + break; + default: + if (isprint(c)) + sprintf(tkbuffer, "#\\%c", c); + else + sprintf(tkbuffer, "#\\0%o", (unsigned int)(unsigned char)c); + break; + } + } + gput_st(f, tkbuffer); + break; +/* -- */ case tc_subr_0: case tc_subr_1: case tc_subr_2: diff -uu -b siod/sliba.c siod.cmm/sliba.c --- siod/sliba.c Sun May 11 07:36:34 1997 +++ siod.cmm/sliba.c Sat Jul 5 14:58:06 1997 @@ -14,6 +14,7 @@ #include #include #include +#include #include "siod.h" #include "siodp.h" @@ -90,18 +91,34 @@ free(ptr->storage_as.lisp_array.data); break;}} +int +char_is_in(char c, char *str, int len) +{ + int i; + for (i = 0 ; i < len ; ++i) + if (c == str[i]) return 1; + return 0; +} +int +sstrcspn(char *str, int slen, char *reject, int rlen) +{ + int i; + for (i = 0 ; i < slen && !char_is_in(str[i], reject, rlen) ; ++i); + return i < slen ? i : i + 1; +} + void array_prin1(LISP ptr,struct gen_printio *f) {int j; switch (ptr->type) {case tc_string: gput_st(f,"\""); - if (strcspn(ptr->storage_as.string.data,"\"\\\n\r\t") == - strlen(ptr->storage_as.string.data)) + if (sstrcspn(ptr->storage_as.string.data, STRDIM(ptr), "\"\\\n\r\t\0", 6) == + STRDIM(ptr)) gput_st(f,ptr->storage_as.string.data); else {int n,c; char cbuff[3]; - n = strlen(ptr->storage_as.string.data); + n = STRDIM(ptr); for(j=0;jstorage_as.string.data[j]) {case '\\': @@ -120,6 +137,9 @@ case '\t': gput_st(f,"\\t"); break; + case '\0': + gput_st(f,"\\N"); + break; default: cbuff[0] = c; cbuff[1] = 0; @@ -176,6 +196,384 @@ no_interrupt(flag); return(s);} +/* added by cmm */ +int sstrcmp(char *s1, int n1, char *s2, int n2); + +LISP +chrcons(char arg) +{ + long iflag = no_interrupt(1); + LISP result = newcell(tc_char); + CHR(result) = arg; + no_interrupt(iflag); + return result; +} + +LISP +is_char(LISP arg) +{ + return CHARP(arg) ? sym_t : NIL; +} + +LISP +char_eq(LISP a, LISP b) +{ + return get_c_char(a) == get_c_char(b) ? sym_t : NIL; +} + +LISP +char_lt(LISP a, LISP b) +{ + return get_c_char(a) < get_c_char(b) ? sym_t : NIL; +} + +LISP +char_gt(LISP a, LISP b) +{ + return char_lt(b, a); +} + +LISP +char_le(LISP a, LISP b) +{ + return char_gt(a, b) ? NIL : sym_t; +} + +LISP +char_ge(LISP a, LISP b) +{ + return char_lt(a, b) ? NIL : sym_t; +} + +LISP +char_ci_eq(LISP a, LISP b) +{ + return char_eq(char_upcase(a), char_upcase(b)); +} + +LISP +char_ci_lt(LISP a, LISP b) +{ + return char_lt(char_upcase(a), char_upcase(b)); +} + +LISP +char_ci_gt(LISP a, LISP b) +{ + return char_gt(char_upcase(a), char_upcase(b)); +} + +LISP +char_ci_le(LISP a, LISP b) +{ + return char_le(char_upcase(a), char_upcase(b)); +} + +LISP +char_ci_ge(LISP a, LISP b) +{ + return char_ge(char_upcase(a), char_upcase(b)); +} + +#define CHAR_PRED(name, pred) LISP name(LISP arg) { return pred(get_c_char(arg)) ? sym_t : NIL; } +CHAR_PRED(is_char_alph, isalpha); +CHAR_PRED(is_char_num, isdigit); +CHAR_PRED(is_char_ws, isspace); +CHAR_PRED(is_char_upper, isupper); +CHAR_PRED(is_char_lower, islower); + +LISP +char_to_int(LISP arg) +{ + return flocons(get_c_char(arg)); +} + +LISP +int_to_char(LISP arg) +{ + long n = get_c_long(arg); + if (n < 0 || n > 255) err("not a valid character code", arg); + return chrcons((char)n); +} + +LISP +char_upcase(LISP arg) +{ + return chrcons(toupper(get_c_char(arg))); +} + +LISP +char_downcase(LISP arg) +{ + return chrcons(tolower(get_c_char(arg))); +} + +LISP +make_string(LISP len, LISP init) +{ + LISP result; + long dim; + if (NNULLP(init) && NCHARP(init)) err("not a char", init); + if NTYPEP(len, tc_flonum) err("not a number", len); + if (FLONM(len) < 0) err("negative length", len); + result = strcons(dim, NULL); + if NNULLP(init) string_fill(result, init); + return result; +} + +LISP +string(LISP args) +{ + long size; + LISP l, s; + char *data; + int i; + size = 0; + for(l = args ; NNULLP(l) ; l = cdr(l)) { + LISP chr = car(l); + if NTYPEP(chr, tc_char) err("not a char", chr); + ++size; + } + s = strcons(size, NULL); + data = s->storage_as.string.data; + data[size] = 0; + i = 0; + for(l = args, i = 0 ; NNULLP(l) ; l = cdr(l), ++i) { + LISP chr = car(l); + data[i] = CHR(chr); + } + return(s); +} + +char * +get_c_sstring_dim(LISP, long *); + +LISP +string_ref(LISP str, LISP idx) +{ + char *data; + long dim; + if NTYPEP(idx, tc_flonum) err("not a number", idx); + data = get_c_sstring_dim(str, &dim); + if (FLONM(idx) < 0) err("negative index", idx); + if (FLONM(idx) >= dim) err("index too large", idx); + return chrcons(data[get_c_long(idx)]); +} + +LISP +string_set(LISP str, LISP idx, LISP chr) +{ + long i; + if NTYPEP(str, tc_string) err("not a string", str); + i = get_c_long(idx); + if (i < 0) err("negative index", idx); + if (FLONM(idx) >= str->storage_as.string.dim) err("index too large", idx); + str->storage_as.string.data[get_c_long(idx)] = get_c_char(chr); + return str; +} + +LISP +string_eq(LISP a, LISP b) +{ + char *s1, *s2; + long n1, n2; + s1 = get_c_string_dim(a, &n1); + s2 = get_c_string_dim(b, &n2); + return sstrcmp(s1, n1, s2, n2) == 0 ? sym_t : NIL; +} + +LISP +string_lt(LISP a, LISP b) +{ + char *s1, *s2; + long n1, n2; + s1 = get_c_string_dim(a, &n1); + s2 = get_c_string_dim(b, &n2); + return sstrcmp(s1, n1, s2, n2) < 0 ? sym_t : NIL; +} + +LISP +string_gt(LISP a, LISP b) +{ + return string_lt(b, a); +} + +LISP +string_le(LISP a, LISP b) +{ + return string_gt(a, b) ? NIL : sym_t; +} + +LISP +string_ge(LISP a, LISP b) +{ + return string_lt(a, b) ? NIL : sym_t; +} + +LISP +string_ci_eq(LISP a, LISP b) +{ + return string_eq(string_upcase(a), string_upcase(b)); +} + +LISP +string_ci_lt(LISP a, LISP b) +{ + return string_lt(string_upcase(a), string_upcase(b)); +} + +LISP +string_ci_gt(LISP a, LISP b) +{ + return string_gt(string_upcase(a), string_upcase(b)); +} + +LISP +string_ci_le(LISP a, LISP b) +{ + return string_le(string_upcase(a), string_upcase(b)); +} + +LISP +string_ci_ge(LISP a, LISP b) +{ + return string_ge(string_upcase(a), string_upcase(b)); +} + +LISP +string_to_list(LISP str) +{ + LISP result; + long iflag; + int i; + char *data; + long dim; + data = get_c_sstring_dim(str, &dim); + result = NIL; + iflag = no_interrupt(1); + for (i = 0 ; i < dim ; ++i) + result = cons(chrcons(data[i]), result); + no_interrupt(iflag); + return reverse(result); +} + +LISP +string_copy(LISP src) +{ + char *data; + long dim; + data = get_c_sstring_dim(src, &dim); + return strcons(dim, data); +} + +LISP +string_fill(LISP str, LISP chr) +{ + int i; + char c; + if (NTYPEP(str, tc_string) && NTYPEP(str, tc_byte_array)) err("not a string", str); + c = get_c_char(chr); + for (i = 0 ; i < str->storage_as.string.dim ; ++i) str->storage_as.string.data[i] = c; + return str; +} + +LISP +is_vector(LISP arg) +{ + return TYPEP(arg, tc_lisp_array) ? sym_t : NIL; +} + +LISP +vector_fill(LISP v, LISP with) +{ + int i; + if NTYPEP(v, tc_lisp_array) err("not a vector", v); + for (i = 0 ; i < v->storage_as.lisp_array.dim ; ++i) v->storage_as.lisp_array.data[i] = with; + return v; +} + +LISP +make_vector(LISP len, LISP init) +{ + LISP result = cons_array(len, cintern("lisp")); + if NNULLP(init) + vector_fill(result, init); + return result; +} + +LISP +vector(LISP args) +{ + long size; + LISP l, s; + LISP *data; + int i; + size = 0; + for(l = args ; NNULLP(l) ; l = cdr(l)) ++size; + s = cons_array(flocons(size), cintern("lisp")); + data = s->storage_as.lisp_array.data; + i = 0; + for(l = args, i = 0 ; NNULLP(l) ; l = cdr(l), ++i) + data[i] = car(l); + return(s); +} + +LISP +vector_length(LISP arg) +{ + if NTYPEP(arg, tc_lisp_array) err("not a vector", arg); + return flocons(arg->storage_as.lisp_array.dim); +} + +LISP +vector_ref(LISP v, LISP k) +{ + if NTYPEP(v, tc_lisp_array) err("not a vector", v); + return aref1(v, k); +} + +LISP +vector_set(LISP v, LISP k, LISP to) +{ + if NTYPEP(v, tc_lisp_array) err("not a vector", v); + return aset1(v, k, to); +} + +LISP +vector_copy(LISP v) +{ + LISP result; + long iflag; + long dim, nbytes; + if NTYPEP(v, tc_lisp_array) err("not a vector", v); + iflag = no_interrupt(1); + result = newcell(tc_lisp_array); + dim = v->storage_as.lisp_array.dim; + nbytes = dim * sizeof(LISP); + result->storage_as.lisp_array.dim = dim; + result->storage_as.lisp_array.data = (LISP *)must_malloc(nbytes); + memcpy(result->storage_as.lisp_array.data, v->storage_as.lisp_array.data, nbytes); + no_interrupt(iflag); + return result; +} + +LISP +vector_to_list(LISP v) +{ + LISP result; + long iflag; + int i; + if NTYPEP(v, tc_lisp_array) err("not a vector", v); + result = NIL; + iflag = no_interrupt(1); + for (i = 0 ; i < v->storage_as.lisp_array.dim ; ++i) + result = cons(v->storage_as.lisp_array.data[i], result); + no_interrupt(iflag); + return reverse(result); +} + +/* -- */ + int rfs_getc(unsigned char **p) {int i; i = **p; @@ -373,20 +771,7 @@ no_interrupt(flag); return(a);} -LISP string_append(LISP args) -{long size; - LISP l,s; - char *data; - size = 0; - for(l=args;NNULLP(l);l=cdr(l)) - size += strlen(get_c_string(car(l))); - s = strcons(size,NULL); - data = s->storage_as.string.data; - data[0] = 0; - for(l=args;NNULLP(l);l=cdr(l)) - strcat(data,get_c_string(car(l))); - return(s);} - +/* changed by cmm */ LISP bytes_append(LISP args) {long size,n,j; LISP l,s; @@ -403,6 +788,13 @@ j += n;} return(s);} +LISP string_append(LISP args) +{ + LISP result = bytes_append(args); + result->type = tc_string; + return result; +} + LISP substring(LISP str,LISP start,LISP end) {long s,e,n; char *data; @@ -416,11 +808,47 @@ if ((e < 0) || (e > n)) err("bad end index",end); return(strcons(e-s,&data[s]));} +/* + Like standard sstrcmp, but doesn't treat NUL's specially + (so requires the lengths as arguments) + */ +int +sstrcmp(char *s1, int n1, char *s2, int n2) +{ + int n = (n1 > n2 ? n2 : n1); + int i; + for (i = 0 ; i < n ; ++i) { + if (s1[i] < s2[i]) return -1; + if (s1[i] > s2[i]) return 1; + } + return n1 - n2; +} + +char * +sstrstr(char *haystack, int hlen, char *needle, int nlen) +{ + int i; + if (hlen == 0) return NULL; + if (nlen == 0) return haystack; + i = 0; + while (1) { + while (haystack[i] != needle[0] && i < hlen) ++i; + if (i >= hlen) return NULL; + if (hlen - i < nlen) return NULL; + if (sstrcmp(haystack + i, nlen, needle, nlen) == 0) return haystack + i; + ++i; + } + /* will never get here */ + return NULL; +} + LISP string_search(LISP token,LISP str) -{char *s1,*s2,*ptr; - s1 = get_c_string(str); - s2 = get_c_string(token); - ptr = strstr(s1,s2); +{ + char *s1,*s2,*ptr; + long n1, n2; + s1 = get_c_string_dim(str, &n1); + s2 = get_c_string_dim(token, &n2); + ptr = sstrstr(s1,n1,s2,n2); if (ptr) return(flocons(ptr - s1)); else @@ -429,33 +857,58 @@ #define IS_TRIM_SPACE(_x) (strchr(" \t\r\n",(_x))) LISP string_trim(LISP str) -{char *start,*end; - start = get_c_string(str); - while(*start && IS_TRIM_SPACE(*start)) ++start; - end = &start[strlen(start)]; +{ + char *start,*end; + if NTYPEP(str, tc_string) err("not a string", str); + start = STRDATA(str); + end = STRDATA(str) + STRDIM(str); + while(IS_TRIM_SPACE(*start) && start < end) ++start; while((end > start) && IS_TRIM_SPACE(*(end-1))) --end; - return(strcons(end-start,start));} + return(strcons(end-start,start)); +} LISP string_trim_left(LISP str) -{char *start,*end; - start = get_c_string(str); - while(*start && IS_TRIM_SPACE(*start)) ++start; - end = &start[strlen(start)]; - return(strcons(end-start,start));} +{ + char *start,*end; + if NTYPEP(str, tc_string) err("not a string", str); + start = STRDATA(str); + end = STRDATA(str) + STRDIM(str); + while(IS_TRIM_SPACE(*start) && start < end) ++start; + return(strcons(end-start,start)); +} LISP string_trim_right(LISP str) -{char *start,*end; - start = get_c_string(str); - end = &start[strlen(start)]; +{ + char *start,*end; + if NTYPEP(str, tc_string) err("not a string", str); + start = STRDATA(str); + end = STRDATA(str) + STRDIM(str); while((end > start) && IS_TRIM_SPACE(*(end-1))) --end; - return(strcons(end-start,start));} + return(strcons(end-start,start)); +} + +/* + Like get_c_string_dim, but doesn't consider float_array's as + strings (should it??) + */ +char *get_c_sstring_dim(LISP x,long *len) +{switch(TYPE(x)) + {case tc_symbol: + *len = strlen(PNAME(x)); + return(PNAME(x)); + case tc_string: + case tc_byte_array: + *len = x->storage_as.string.dim; + return(x->storage_as.string.data); + default: + err("not a symbol or string",x); + return(NULL);}} LISP string_upcase(LISP str) {LISP result; char *s1,*s2; long j,n; - s1 = get_c_string(str); - n = strlen(s1); + s1 = get_c_sstring_dim(str, &n); result = strcons(n,s1); s2 = get_c_string(result); for(j=0;j= '0' && (c) < '8') LISP lreadsharp(struct gen_readio *f) {LISP obj,l,result; @@ -539,6 +1004,41 @@ return(NIL); case 't': return(flocons(1)); + case '\\': + c = GETC_FCN(f); + if (isoctal(c)) { + char sec; + sec = GETC_FCN(f); + UNGETC_FCN(sec, f); + if (!isoctal(sec)) return chrcons(c); + else { + char buf[64]; + int i; + long code; + for (i = 0 ; i < 63 && isoctal(c) ; ++i) { + buf[i] = c; + c = GETC_FCN(f); + } + if (i >= 63) err("buffer overflow when reading char octal code", NIL); + UNGETC_FCN(c, f); + buf[i] = '\0'; + code = strtol(buf, NULL, 8); + if (code == LONG_MIN || code == LONG_MAX) err("invalid character code", NIL); + return int_to_char(flocons(code)); + } + } else if (toupper(c) != 'S' && toupper(c) != 'N') { + return chrcons(c); + } else { + char sec = GETC_FCN(f); + UNGETC_FCN(sec, f); + if (!isalpha(sec)) return chrcons(c); + switch (toupper(c)) { + case 'S': + return try_match(f, "pace", ' '); + case 'N': + return try_match(f, "ewline", '\n'); + } + } default: return(err("readsharp syntax not handled",NIL));}} @@ -607,6 +1107,10 @@ return((FLONM(a) == FLONM(b)) ? sym_t : NIL); case tc_symbol: return(NIL); +/* added by cmm */ + case tc_char: + return((CHR(a) == CHR(b)) ? sym_t : NIL); +/* -- */ default: p = get_user_type_hooks(atype); if (p->equal) @@ -977,6 +1481,15 @@ {if NFLONUMP(x) err("not a number",x); return(FLONM(x));} +/* added by cmm */ +char +get_c_char(LISP x) +{ + if NCHARP(x) err("not a char", x); + return CHR(x); +} +/* -- */ + LISP make_list(LISP x,LISP v) {long n; LISP l; @@ -1053,7 +1566,7 @@ LISP string_length(LISP string) {if NTYPEP(string,tc_string) err_wta_str(string); - return(flocons(strlen(string->storage_as.string.data)));} + return flocons(STRDIM(string));} LISP string_dim(LISP string) {if NTYPEP(string,tc_string) err_wta_str(string); @@ -2088,5 +2601,53 @@ init_subr_1("parser_fasl",parser_fasl); setvar(cintern("*parser_fasl.scm-loaded*"),a_true_value(),NIL); init_subr_2("parser_fasl_hook",parser_fasl_hook); + /* added by cmm */ + init_subr_1("char?", is_char); + init_subr_2("char=?", char_eq); + init_subr_2("char?",char_gt); + init_subr_2("char<=?",char_le); + init_subr_2("char>=?",char_ge); + init_subr_2("char-ci=?", char_ci_eq); + init_subr_2("char-ci?",char_ci_gt); + init_subr_2("char-ci<=?",char_ci_le); + init_subr_2("char-ci>=?",char_ci_ge); + init_subr_1("char-alphabetic?", is_char_alph); + init_subr_1("char-numeric?", is_char_num); + init_subr_1("char-whitespace?", is_char_ws); + init_subr_1("char-upper-case?", is_char_upper); + init_subr_1("char-lower-case?", is_char_lower); + init_subr_1("char->integer", char_to_int); + init_subr_1("integer->char", int_to_char); + init_subr_1("char-upcase", char_upcase); + init_subr_1("char-downcase", char_downcase); + init_subr_2("make-string", make_string); + init_lsubr("string", string); + init_subr_1("list->string", string); + init_subr_2("string-ref", string_ref); + init_subr_3("string-set!", string_set); + init_subr_2("string=?", string_eq); + init_subr_2("string?", string_gt); + init_subr_2("string<=?", string_le); + init_subr_2("string>=?", string_ge); + init_subr_2("string-ci=?", string_ci_eq); + init_subr_2("string-ci?", string_ci_gt); + init_subr_2("string-ci<=?", string_ci_le); + init_subr_2("string-ci>=?", string_ci_ge); + init_subr_1("string->list", string_to_list); + init_subr_1("string-copy", string_copy); + init_subr_2("string-fill!", string_fill); + init_subr_1("vector?", is_vector); + init_subr_2("make-vector", make_vector); + init_lsubr("vector", vector); + init_subr_1("list->vector", vector); + init_subr_2("vector-ref", vector_ref); + init_subr_3("vector-set!", vector_set); + init_subr_1("vector->list", vector_to_list); + init_subr_1("vector-copy", vector_copy); + init_subr_2("vector-fill!", vector_fill); + /* -- */ init_sliba_version();} -