diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2009-11-23 15:46:24 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2009-11-23 15:46:24 -0800 |
commit | b6f5aadfccea8bccadd6c56b57fe6f6b80cfc213 (patch) | |
tree | cd71b8fefd57c2c1d4d6e9f7f3a633575f26b03b | |
parent | 4a1556a848c5bfb527cecb2b823a750ba63e6f80 (diff) | |
download | txr-b6f5aadfccea8bccadd6c56b57fe6f6b80cfc213.tar.gz txr-b6f5aadfccea8bccadd6c56b57fe6f6b80cfc213.tar.bz2 txr-b6f5aadfccea8bccadd6c56b57fe6f6b80cfc213.zip |
Improving portability. It is no longer assumed that pointers
can be converted to a type long and vice versa. The configure
script tries to detect the appropriate type to use. Also,
some run-time checking is performed in the streams module
to detect which conversions specifier strings to use for
printing numbers.
-rw-r--r-- | ChangeLog | 70 | ||||
-rw-r--r-- | Makefile | 16 | ||||
-rwxr-xr-x | configure | 154 | ||||
-rw-r--r-- | dep.mk | 27 | ||||
-rw-r--r-- | gc.c | 3 | ||||
-rw-r--r-- | hash.c | 25 | ||||
-rw-r--r-- | lib.c | 53 | ||||
-rw-r--r-- | lib.h | 24 | ||||
-rw-r--r-- | match.c | 15 | ||||
-rw-r--r-- | parser.h | 2 | ||||
-rw-r--r-- | parser.l | 10 | ||||
-rw-r--r-- | parser.y | 3 | ||||
-rw-r--r-- | regex.c | 11 | ||||
-rw-r--r-- | regex.h | 8 | ||||
-rw-r--r-- | stream.c | 55 | ||||
-rw-r--r-- | txr.c | 1 | ||||
-rw-r--r-- | unwind.c | 1 | ||||
-rw-r--r-- | unwind.h | 2 | ||||
-rw-r--r-- | utf8.c | 1 |
19 files changed, 377 insertions, 104 deletions
@@ -1,3 +1,73 @@ +2009-11-23 Kaz Kylheku <kkylheku@gmail.com> + + Improving portability. It is no longer assumed that pointers + can be converted to a type long and vice versa. The configure + script tries to detect the appropriate type to use. Also, + some run-time checking is performed in the streams module + to detect which conversions specifier strings to use for + printing numbers. + + * Makefile (conftest, conftest.o, conftest.syms): New targets. + Used by the configure script. + + * configure (intptr, nm): New configuration variables. + Generating config.make is no longer the last step; compiler tests are + performed after config.make is set up, so that rules in the Makefile + can be used for doing the compiling. (This is the cleanest way to do + it, since the paths to the tools may contain Make variable expansion + syntax). New steps are added to try to detect whether the compiler has + a wider integer type than the c89 long, and which of the available + types (including, potentially, the extra wide type) is suitable for + holding a pointer. Results are generated into a header config.h. + + * dep.mk: Regenerated. + + * lib.h (NUM_MAX, NUM_MIN): Now derived from INT_PTR_MAX and + INT_PTR_MIN macros, which come from config.h. + (cnum): New typedef name. + (cobj ops, tag, auto_str, static_str, litptr, lit_noex): + Changed long to cnum. + (num, c_num): Declaration updated. + + * lib.c (equal, length, num, c_num, plus, minus, neg, search_str, + cat_str, vector, vec_set_fill, obj_print, obj_pprint): Changed + long to cnum. + + * gc.c (mark_obj): Changed long to cnum. + + * hash.c (stuct hash, ll_hash, hash_mark, hash_grow, + hash_process_weak): Changed long to cnum. + + * match.c (complex_open, do_output_line, do_output, match_files): + Changed long to cnum. + + * parser.h (lineno): Declaration updated. + + * parser.l (lineno): Redefined as cnum. + (grammar): Changed long to cnum. + + * parser.y (%union/yystype): num member changed to cnum. + of config.h added. + + * regex.c (nfa_run, nfa_machine_match_span, search_regex): + Changed long to cnum. + + * regex.h (struct nfa_machine): Members last_accept_pos and count + changed to cnum. + (nfa_run, nfa_machine_match_span): Declarations updated. + + * stream.c (struct fmt): New type. + (fmt_tab): New static array. + (num_fmt): New static pointer. + (detect_format_string): New function. + (vformat): Changed long to cnum. Formatting of numbers uses + num_fmt. + (stream_init): Call detect_format_string. + + * txr.c, unwind.c, utf8.c: include config.h. + + * unwind.h (internal_error): Local declaration of num updated. + 2009-11-21 Kaz Kylheku <kkylheku@gmail.com> Introducing symbol packages. Internal symbols are now in @@ -59,7 +59,7 @@ clean: .PHONY: distclean distclean: clean - rm -f config.make config.log + rm -f config.h config.make config.log .PHONY: depend depend: @@ -101,3 +101,17 @@ install: $(PROG) config.make: @echo "config.make missing: you didn't run ./configure" @exit 1 + +# +# Special targets used by ./configure +# + +conftest: conftest.c + $(CC) -o $@ $^ + +conftest.o: CFLAGS := $(LANG_FLAGS) + +conftest.o: conftest.c + +conftest.syms: conftest.o + $(NM) -t o -P $^ > $@ @@ -104,10 +104,12 @@ mandir=${mandir-'$(prefix)/share/man'} cross=${cross-} compiler_prefix=${compiler_prefix-} cc=${cc-'$(cross)$(compiler_prefix)gcc'} +intptr= tool_prefix=${tool_prefix-} lex=${lex-'$(cross)$(tool_prefix)flex'} lexlib=${lexlib--lfl} yacc=${yacc-'$(cross)$(tool_prefix)yacc'} +nm=${nm-'$(cross)$(tool_prefix)nm'} opt_flags=${opt_flags--O2} lang_flags=${lang_flags--ansi -std=c89 -D_POSIX_C_SOURCE=2} diag_flags=${diag_flags--Wall} @@ -208,6 +210,12 @@ cc [$cc] compiling C sources to object files, and for linking object files to executables. This becomes the CC variable in the Makefile. +intptr [$intptr] + + Specifies the name of the C integer type wide enough such that a pointer + value can be converted to it. If this is blank, the configure script + will try to auto detect it. + tool_prefix [$tool_prefix] Specifies a prefix to be added to tool commands other than the @@ -226,6 +234,10 @@ yacc [$yacc] Specifies the program to use for compiling yacc scanners to C. +nm [$nm] + + Specifies the nm program for dumping symbols from an object file. + opt_flags [$opt_flags] Specifies optimization flags to use for compiling and linking @@ -403,20 +415,9 @@ else fi # -# Save configuration in config.log -# -cat > config.log <<! - -Configured on $(date) using - - $cmdline - -! - -# # Finally, we generate config.make # -printf "generating config.make\n" +printf "generating config.make ...\n" cat > config.make <<! # absolute path to source code directory @@ -454,6 +455,7 @@ CC := $cc LEX := $lex LEXLIB := $lexlib YACC := $yacc +NM := $nm OPT_FLAGS := $opt_flags LANG_FLAGS := $lang_flags @@ -465,9 +467,137 @@ TXR_DBG_OPTS := $txr_dbg_opts ! # +# Start config.h header +# +> config.h + +# +# Check C compiler sanity +# +printf "Checking whether your C compiler can make a simple executable ... " + +cat > conftest.c <<! +#include <stdio.h> +int main(void) +{ + printf("Hello, world!\n"); + return 0; +} +! + +if ! make conftest > /dev/null 2>&1 || ! [ -x conftest ] ; then + printf "failed\n" + exit 1 +fi + +rm -f conftest +printf "okay\n" + +# +# Check what kind of C type we have for integers wider than long, +# if any. +# +printf "Checking what C type we have for integers wider than \"long\" ... " + +for try_type in int64 __int64 "long long" ; do + cat > conftest.c <<! +$try_type value; +! + rm -f conftest.o + if make conftest.o > /dev/null 2>&1 ; then + longlong=$try_type + break + fi +done + +if [ -n "$longlong" ] ; then + printf '"%s"\n' "$longlong" + printf "#define HAVE_LONGLONG_T 1\n" >> config.h + printf "typedef $longlong longlong_t;\n" >> config.h +else + printf "none\n" +fi + +printf "Checking what C integer type can hold a pointer ... " + +if [ -z "$intptr" ] ; then + cat > conftest.c <<! +#include "config.h" +char sizeof_ptr[sizeof (char *)]; +char sizeof_short[sizeof (short)]; +char sizeof_int[sizeof (int)]; +char sizeof_long[sizeof (long)]; +#ifdef HAVE_LONGLONG_T +char sizeof_longlong_t[sizeof (longlong_t)]; +#endif +! + rm -f conftest.o conftest.syms + + if ! make conftest.syms > /dev/null 2>&1 ; then + echo "failed" + exit 1; + fi + + sizeof_ptr=0 + sizeof_short=0 + sizeof_int=0 + sizeof_long=0 + sizeof_longlong_t=0 + + while read symbol type offset size ; do + eval "size=$(( 0$size + 0 ))" + eval $(printf "%s=%d\n" "$symbol" "$size") + done < conftest.syms + + rm -f conftest.syms conftest.o + + if [ $sizeof_ptr -eq 0 ] ; then + printf "failed\n" + exit 1; + fi + + if [ $sizeof_ptr -eq $sizeof_short ] ; then + intptr="short" + elif [ $sizeof_ptr -eq $sizeof_int ] ; then + intptr="int" + elif [ $sizeof_ptr -eq $sizeof_long ] ; then + intptr="long" + elif [ $sizeof_ptr -eq $sizeof_long_long_t ] ; then + intptr="longlong_t" + fi + + if [ -z "$intptr" ] ; then + printf "failed\n" + exit 1; + fi +fi + +printf '"%s"\n' "$intptr" +printf "typedef $intptr int_ptr_t;\n" >> config.h +intptr_max=$(( (1 << ( sizeof_ptr * 8 - 1 )) - 1 )) +printf "#define INT_PTR_MAX %d\n" $intptr_max >> config.h +printf "#define INT_PTR_MIN -%d\n" $intptr_max >> config.h + +# +# Clean up +# +rm -f conftest conftest.c conftest.o conftest.syms + +# +# Save configuration in config.log +# +cat > config.log <<! + +Configured on $(date) using + + $cmdline + +! +# # Parting message# # cat <<! + Configuration seems to have been successful. The next step is one of these two. @@ -1,12 +1,15 @@ -parser.tab.o: $(top_srcdir)/lib.h $(top_srcdir)/regex.h $(top_srcdir)/parser.h -utf8.o: $(top_srcdir)/lib.h $(top_srcdir)/utf8.h -lib.o: $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/stream.h $(top_srcdir)/utf8.h -lex.yy.o: y.tab.h $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/stream.h $(top_srcdir)/utf8.h $(top_srcdir)/parser.h -regex.o: $(top_srcdir)/lib.h $(top_srcdir)/unwind.h $(top_srcdir)/regex.h -y.tab.o: $(top_srcdir)/lib.h $(top_srcdir)/regex.h $(top_srcdir)/utf8.h $(top_srcdir)/parser.h -unwind.o: $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/stream.h $(top_srcdir)/txr.h $(top_srcdir)/unwind.h -txr.o: $(top_srcdir)/lib.h $(top_srcdir)/stream.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/parser.h $(top_srcdir)/match.h $(top_srcdir)/utf8.h $(top_srcdir)/txr.h -match.o: $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/regex.h $(top_srcdir)/stream.h $(top_srcdir)/parser.h $(top_srcdir)/txr.h $(top_srcdir)/utf8.h $(top_srcdir)/match.h -stream.o: $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/stream.h $(top_srcdir)/utf8.h -gc.o: $(top_srcdir)/lib.h $(top_srcdir)/stream.h $(top_srcdir)/hash.h $(top_srcdir)/txr.h $(top_srcdir)/gc.h -hash.o: $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/hash.h +parser.tab.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/regex.h $(top_srcdir)/parser.h +utf8.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/utf8.h +lib.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/hash.h $(top_srcdir)/unwind.h $(top_srcdir)/stream.h $(top_srcdir)/utf8.h +lex.yy.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h y.tab.h $(top_srcdir)/gc.h $(top_srcdir)/stream.h $(top_srcdir)/utf8.h $(top_srcdir)/parser.h +popen_getwc.o: +test-sprintf.o: +test.o: +regex.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/unwind.h $(top_srcdir)/regex.h +y.tab.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/regex.h $(top_srcdir)/utf8.h $(top_srcdir)/parser.h +unwind.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/stream.h $(top_srcdir)/txr.h $(top_srcdir)/unwind.h +txr.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/stream.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/parser.h $(top_srcdir)/match.h $(top_srcdir)/utf8.h $(top_srcdir)/txr.h +match.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/regex.h $(top_srcdir)/stream.h $(top_srcdir)/parser.h $(top_srcdir)/txr.h $(top_srcdir)/utf8.h $(top_srcdir)/match.h +stream.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/stream.h $(top_srcdir)/utf8.h +gc.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/stream.h $(top_srcdir)/hash.h $(top_srcdir)/txr.h $(top_srcdir)/gc.h +hash.o: $(top_srcdir)/config.h $(top_srcdir)/lib.h $(top_srcdir)/gc.h $(top_srcdir)/unwind.h $(top_srcdir)/hash.h @@ -31,6 +31,7 @@ #include <setjmp.h> #include <dirent.h> #include <wchar.h> +#include "config.h" #include "lib.h" #include "stream.h" #include "hash.h" @@ -231,7 +232,7 @@ tail_call: { val alloc_size = obj->v.vec[-2]; val fill_ptr = obj->v.vec[-1]; - long i, fp = c_num(fill_ptr); + cnum i, fp = c_num(fill_ptr); mark_obj(alloc_size); mark_obj(fill_ptr); @@ -32,6 +32,7 @@ #include <assert.h> #include <setjmp.h> #include <limits.h> +#include "config.h" #include "lib.h" #include "gc.h" #include "unwind.h" @@ -48,8 +49,8 @@ struct hash { hash_flags_t flags; struct hash *next; val table; - long modulus; - long count; + cnum modulus; + cnum count; }; /* @@ -76,7 +77,7 @@ static long hash_c_str(const wchar_t *str) return h; } -static long ll_hash(val obj) +static cnum ll_hash(val obj) { if (obj == nil) return NUM_MAX; @@ -94,14 +95,14 @@ static long ll_hash(val obj) return c_num(obj) & NUM_MAX; case SYM: case PKG: - return ((long) obj) & NUM_MAX; + return ((cnum) obj) & NUM_MAX; case FUN: - return ((long) obj->f.f.interp_fun + ll_hash(obj->f.env)) & NUM_MAX; + return ((cnum) obj->f.f.interp_fun + ll_hash(obj->f.env)) & NUM_MAX; case VEC: { val fill = obj->v.vec[vec_fill]; - long i, h = ll_hash(obj->v.vec[vec_fill]); - long len = c_num(fill); + cnum i, h = ll_hash(obj->v.vec[vec_fill]); + cnum len = c_num(fill); for (i = 0; i < len; i++) h = (h + ll_hash(obj->v.vec[i])) & NUM_MAX; @@ -116,7 +117,7 @@ static long ll_hash(val obj) case COBJ: if (obj->co.ops->hash) return obj->co.ops->hash(obj); - return ((long) obj) & NUM_MAX; + return ((cnum) obj) & NUM_MAX; } internal_error("unhandled case in equal function"); @@ -140,7 +141,7 @@ void hash_destroy(val hash) void hash_mark(val hash) { struct hash *h = (struct hash *) hash->co.handle; - long i; + cnum i; switch (h->flags) { case hash_weak_none: @@ -195,8 +196,8 @@ static struct cobj_ops hash_ops = { void hash_grow(struct hash *h) { - long i; - long new_modulus = 2 * h->modulus; + cnum i; + cnum new_modulus = 2 * h->modulus; val new_table = vector(num(new_modulus)); bug_unless (new_modulus > h->modulus); @@ -276,7 +277,7 @@ val remhash(val hash, val key) void hash_process_weak(void) { struct hash *h; - long i; + cnum i; for (h = reachable_weak_hashes; h != 0; h = h->next) { switch (h->flags) { @@ -34,6 +34,7 @@ #include <dirent.h> #include <setjmp.h> #include <wchar.h> +#include "config.h" #include "lib.h" #include "gc.h" #include "hash.h" @@ -410,7 +411,7 @@ val flatten(val list) return mappend(func_f1(nil, flatten_helper), list); } -long c_num(val num); +cnum c_num(val num); val equal(val left, val right) { @@ -489,7 +490,7 @@ val equal(val left, val right) return nil; case VEC: if (type(right) == VEC) { - long i, fill; + cnum i, fill; if (!equal(left->v.vec[vec_fill], right->v.vec[vec_fill])) return nil; fill = c_num(left->v.vec[vec_fill]); @@ -620,7 +621,7 @@ val proper_listp(val obj) val length(val list) { - long len = 0; + cnum len = 0; while (consp(list)) { len++; list = cdr(list); @@ -628,17 +629,17 @@ val length(val list) return num(len); } -val num(long n) +val num(cnum n) { numeric_assert (n >= NUM_MIN && n <= NUM_MAX); return (val) ((n << TAG_SHIFT) | TAG_NUM); } -long c_num(val num) +cnum c_num(val num) { if (!is_num(num)) type_mismatch(lit("~s is not a number"), num, nao); - return ((long) num) >> TAG_SHIFT; + return ((cnum) num) >> TAG_SHIFT; } val nump(val num) @@ -648,8 +649,8 @@ val nump(val num) val plus(val anum, val bnum) { - long a = c_num(anum); - long b = c_num(bnum); + cnum a = c_num(anum); + cnum b = c_num(bnum); numeric_assert (a <= 0 || b <= 0 || NUM_MAX - b >= a); numeric_assert (a >= 0 || b >= 0 || NUM_MIN - b >= a); @@ -659,8 +660,8 @@ val plus(val anum, val bnum) val minus(val anum, val bnum) { - long a = c_num(anum); - long b = c_num(bnum); + cnum a = c_num(anum); + cnum b = c_num(bnum); numeric_assert (b != NUM_MIN || NUM_MIN == -NUM_MAX); numeric_assert (a <= 0 || -b <= 0 || NUM_MAX + b >= a); @@ -671,7 +672,7 @@ val minus(val anum, val bnum) val neg(val anum) { - long n = c_num(anum); + cnum n = c_num(anum); return num(-n); } @@ -838,8 +839,8 @@ val search_str(val haystack, val needle, val start_num, val from_end) return nil; } else { val h_is_lazy = lazy_stringp(haystack); - long start = c_num(start_num); - long good = -1, pos = -1; + cnum start = c_num(start_num); + cnum good = -1, pos = -1; const wchar_t *n = c_str(needle), *h; if (!h_is_lazy) { @@ -915,10 +916,10 @@ val sub_str(val str_in, val from, val to) val cat_str(val list, val sep) { - long total = 0; + cnum total = 0; val iter; wchar_t *str, *ptr; - long len_sep = sep ? c_num(length_str(sep)) : 0; + cnum len_sep = sep ? c_num(length_str(sep)) : 0; for (iter = list; iter != nil; iter = cdr(iter)) { val item = car(iter); @@ -943,7 +944,7 @@ val cat_str(val list, val sep) for (ptr = str, iter = list; iter != nil; iter = cdr(iter)) { val item = car(iter); - long len; + cnum len; if (!item) continue; if (stringp(item)) { @@ -1364,7 +1365,7 @@ val chain(val fun1_list) val vector(val alloc) { - long alloc_plus = c_num(alloc) + 2; + cnum alloc_plus = c_num(alloc) + 2; val vec = make_obj(); val *v = (val *) chk_malloc(alloc_plus * sizeof *v); vec->v.type = VEC; @@ -1385,14 +1386,14 @@ val vec_set_fill(val vec, val fill) type_check(vec, VEC); { - long new_fill = c_num(fill); - long old_fill = c_num(vec->v.vec[vec_fill]); - long old_alloc = c_num(vec->v.vec[vec_alloc]); - long fill_delta = new_fill - old_fill; - long alloc_delta = new_fill - old_alloc; + cnum new_fill = c_num(fill); + cnum old_fill = c_num(vec->v.vec[vec_fill]); + cnum old_alloc = c_num(vec->v.vec[vec_alloc]); + cnum fill_delta = new_fill - old_fill; + cnum alloc_delta = new_fill - old_alloc; if (alloc_delta > 0) { - long new_alloc = max(new_fill, 2*old_alloc); + cnum new_alloc = max(new_fill, 2*old_alloc); val *newvec = (val *) chk_realloc(vec->v.vec - 2, (new_alloc + 2)*sizeof *newvec); vec->v.vec = newvec + 2; @@ -1400,7 +1401,7 @@ val vec_set_fill(val vec, val fill) } if (fill_delta > 0) { - long i; + cnum i; for (i = old_fill; i < new_fill; i++) vec->v.vec[i] = nil; } @@ -2011,7 +2012,7 @@ void obj_print(val obj, val out) return; case VEC: { - long i, fill = c_num(obj->v.vec[vec_fill]); + cnum i, fill = c_num(obj->v.vec[vec_fill]); put_string(out, lit("#(")); for (i = 0; i < fill; i++) { obj_print(obj->v.vec[i], out); @@ -2081,7 +2082,7 @@ void obj_pprint(val obj, val out) return; case VEC: { - long i, fill = c_num(obj->v.vec[vec_fill]); + cnum i, fill = c_num(obj->v.vec[vec_fill]); put_string(out, lit("#(")); for (i = 0; i < fill; i++) { obj_pprint(obj->v.vec[i], out); @@ -30,8 +30,10 @@ #define TAG_NUM 1 #define TAG_CHR 2 #define TAG_LIT 3 -#define NUM_MAX (LONG_MAX/4) -#define NUM_MIN (LONG_MIN/4) +#define NUM_MAX (INT_PTR_MAX/4) +#define NUM_MIN (INT_PTR_MIN/4) + +typedef int_ptr_t cnum; typedef enum type { NUM = TAG_NUM, CHR = TAG_CHR, LIT = TAG_LIT, CONS, @@ -145,7 +147,7 @@ struct cobj_ops { void (*print)(val self, val stream); void (*destroy)(val self); void (*mark)(val self); - long (*hash)(val self); + cnum (*hash)(val self); }; union obj { @@ -161,7 +163,7 @@ union obj { struct cobj co; }; -inline long tag(val obj) { return ((long) obj) & TAG_MASK; } +inline cnum tag(val obj) { return ((cnum) obj) & TAG_MASK; } inline int is_ptr(val obj) { return obj && tag(obj) == TAG_PTR; } inline int is_num(val obj) { return tag(obj) == TAG_NUM; } inline int is_chr(val obj) { return tag(obj) == TAG_CHR; } @@ -174,20 +176,20 @@ inline type_t type(val obj) inline val auto_str(const wchar_t *str) { - return (val) ((long) (str) | TAG_LIT); + return (val) ((cnum) (str) | TAG_LIT); } inline val static_str(const wchar_t *str) { - return (val) ((long) (str) | TAG_LIT); + return (val) ((cnum) (str) | TAG_LIT); } inline wchar_t *litptr(val obj) { - return (wchar_t *) ((long) obj & ~TAG_MASK); + return (wchar_t *) ((cnum) obj & ~TAG_MASK); } -#define lit_noex(strlit) ((obj_t *) ((long) (L ## strlit) | TAG_LIT)) +#define lit_noex(strlit) ((obj_t *) ((cnum) (L ## strlit) | TAG_LIT)) #define lit(strlit) lit_noex(strlit) extern val keyword_package; @@ -245,7 +247,7 @@ val tree_find(val obj, val tree); val some_satisfy(val list, val pred, val key); val all_satisfy(val list, val pred, val key); val none_satisfy(val list, val pred, val key); -long c_num(val num); +cnum c_num(val num); val nump(val num); val equal(val left, val right); unsigned char *chk_malloc(size_t size); @@ -259,8 +261,8 @@ val atom(val obj); val listp(val obj); val proper_listp(val obj); val length(val list); -val num(long val); -long c_num(val num); +val num(cnum val); +cnum c_num(val num); val plus(val anum, val bnum); val minus(val anum, val bnum); val neg(val num); @@ -33,6 +33,7 @@ #include <setjmp.h> #include <stdarg.h> #include <wchar.h> +#include "config.h" #include "lib.h" #include "gc.h" #include "unwind.h" @@ -633,7 +634,7 @@ fpip_t complex_open(val name, val output) fpip_t ret = { 0, 0 }; const wchar_t *namestr = c_str(name); - long len = c_num(length_str(name)); + cnum len = c_num(length_str(name)); if (len == 0) return ret; @@ -802,7 +803,7 @@ void do_output_line(val bindings, val specline, val bind_a = mapcar(func_n1(bind_car), bind_cp); do_output_line(bind_a, single_clauses, spec_lineno, out); } else if (!zerop(max_depth)) { - long i; + cnum i; for (i = 0; i < c_num(max_depth); i++) { val bind_a = mapcar(func_n1(bind_car), bind_cp); @@ -868,7 +869,7 @@ void do_output(val bindings, val specs, val out) val bind_a = mapcar(func_n1(bind_car), bind_cp); do_output(bind_a, single_clauses, out); } else if (!zerop(max_depth)) { - long i; + cnum i; for (i = 0; i < c_num(max_depth); i++) { val bind_a = mapcar(func_n1(bind_car), bind_cp); @@ -899,7 +900,7 @@ val match_files(val spec, val files, val data_linenum) { val data = nil; - long data_lineno = 0; + cnum data_lineno = 0; if (listp(first_file_parsed)) { data = first_file_parsed; @@ -950,8 +951,8 @@ repeat_spec_same_data: if (sym == skip) { val max = first(rest(first_spec)); - long cmax = nump(max) ? c_num(max) : 0; - long reps = 0; + cnum cmax = nump(max) ? c_num(max) : 0; + cnum reps = 0; if (rest(specline)) sem_error(spec_linenum, @@ -1265,7 +1266,7 @@ repeat_spec_same_data: if (success) { if (consp(success)) { cons_bind (new_data, new_line, success); - long new_lineno = c_num(new_line); + cnum new_lineno = c_num(new_line); bug_unless (new_lineno >= data_lineno); @@ -25,7 +25,7 @@ */ #include <stdio.h> -extern long lineno; +extern cnum lineno; extern int errors; extern val yyin_stream; extern const wchar_t *spec_file; @@ -34,8 +34,9 @@ #include <errno.h> #include <dirent.h> #include <wchar.h> -#include "y.tab.h" +#include "config.h" #include "lib.h" +#include "y.tab.h" #include "gc.h" #include "stream.h" #include "utf8.h" @@ -58,7 +59,7 @@ val yyin_stream; -long lineno = 1; +cnum lineno = 1; int opt_loglevel = 1; /* 0 - quiet; 1 - normal; 2 - verbose */ int opt_nobindings = 0; int opt_arraydims = 1; @@ -190,7 +191,7 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} %% <SPECIAL,NESTED>{TOK} { - long val; + cnum val; char *errp; @@ -217,6 +218,9 @@ UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} && errno == ERANGE) yyerror("numeric overflow in token"); + if (val < NUM_MIN || val > NUM_MAX) + yyerror("numeric overflow in token"); + yylval.num = val; return NUMBER; } @@ -30,6 +30,7 @@ #include <assert.h> #include <limits.h> #include <dirent.h> +#include "config.h" #include "lib.h" #include "regex.h" #include "utf8.h" @@ -50,7 +51,7 @@ static val parsed_spec; wchar_t *lexeme; union obj *obj; wchar_t chr; - long num; + cnum num; } %token <lexeme> TEXT IDENT KEYWORD ALL SOME NONE MAYBE CASES AND OR END COLLECT @@ -32,6 +32,7 @@ #include <dirent.h> #include <setjmp.h> #include <dirent.h> +#include "config.h" #include "lib.h" #include "unwind.h" #include "regex.h" @@ -912,7 +913,7 @@ int nfa_move(nfa_state_t **in, int nin, nfa_state_t **out, wchar_t ch) * determines the match length (defaulting to zero * if no acceptance states were encountered). */ -long nfa_run(nfa_t nfa, const wchar_t *str) +cnum nfa_run(nfa_t nfa, const wchar_t *str) { const wchar_t *last_accept_pos = 0, *ptr = str; unsigned visited = nfa.start->a.visited + 1; @@ -953,7 +954,7 @@ long nfa_run(nfa_t nfa, const wchar_t *str) return last_accept_pos ? last_accept_pos - str : -1; } -long nfa_machine_match_span(nfa_machine_t *nfam) +cnum nfa_machine_match_span(nfa_machine_t *nfam) { return nfam->last_accept_pos; } @@ -1080,12 +1081,12 @@ val search_regex(val haystack, val needle_regex, val start, return nil; } else { if (from_end) { - long i; - long s = c_num(start); + cnum i; + cnum s = c_num(start); const wchar_t *h = c_str(haystack); for (i = c_num(length_str(haystack)) - 1; i >= s; i--) { - long span = nfa_run(*pnfa, h + i); + cnum span = nfa_run(*pnfa, h + i); if (span >= 0) return cons(num(i), num(span)); } @@ -145,22 +145,22 @@ typedef enum nfam_result { } nfam_result_t; typedef struct nfa_machine { - long last_accept_pos; + cnum last_accept_pos; unsigned visited; nfa_state_t **move, **clos, **stack; int nmove, nclos; - long count; + cnum count; nfa_t nfa; } nfa_machine_t; nfa_t nfa_compile_regex(val regex); void nfa_free(nfa_t); -long nfa_run(nfa_t nfa, const wchar_t *str); +cnum nfa_run(nfa_t nfa, const wchar_t *str); void nfa_machine_reset(nfa_machine_t *); void nfa_machine_init(nfa_machine_t *, nfa_t); void nfa_machine_cleanup(nfa_machine_t *); nfam_result_t nfa_machine_feed(nfa_machine_t *, wchar_t ch); -long nfa_machine_match_span(nfa_machine_t *); +cnum nfa_machine_match_span(nfa_machine_t *); val regex_compile(val regex_sexp); val regexp(val); nfa_t *regex_nfa(val); @@ -35,6 +35,7 @@ #include <wchar.h> #include <unistd.h> #include <sys/wait.h> +#include "config.h" #include "lib.h" #include "gc.h" #include "unwind.h" @@ -612,6 +613,44 @@ val get_byte(val stream) } } +struct fmt { + size_t minsize; + const char *dec; + const char *oct; + const char *hex; + const char *HEX; +}; + +static struct fmt fmt_tab[] = { + { sizeof(short),"%hd", "%ho", "%hx", "%hX" }, + { sizeof(int), "%d", "%o", "%x", "%X" }, + { sizeof(long), "%ld", "%lo", "%lx", "%llX" }, + { sizeof(cnum), "%lld", "%llo", "%llx", "%llX" }, + { sizeof(cnum), "%Ld", "%Lo", "%Lx", "%llX" }, + { sizeof(cnum), "%qd", "%qo", "%qx", "%qX", }, + { sizeof(cnum), "%I64d", "%I64o", "%I64x", "%I64X" }, + { 0, 0, 0, 0, 0 } +}; + +static struct fmt *num_fmt; + +static void detect_format_string(void) +{ + struct fmt *f; + char buf[64]; + cnum num = 1234; + + for (f = fmt_tab; f->minsize != 0; f++) { + memset(buf, 0, sizeof buf); + if (f->minsize != sizeof num) + continue; + if (sprintf(buf, f->dec, num) == 4 && strcmp(buf, "1234") == 0) { + num_fmt = f; + break; + } + } +} + static val vformat_num(val stream, const char *str, int width, int left, int pad, int precision) { @@ -681,7 +720,7 @@ val vformat(val stream, val fmtstr, va_list vl) } state = vf_init, saved_state = vf_init; int width = 0, precision = 0, digits = 0; int left = 0, zeropad = 0; - long value; + cnum value; void *ptr; char num_buf[64]; @@ -798,17 +837,17 @@ val vformat(val stream, val fmtstr, va_list vl) case 'x': obj = va_arg(vl, val); value = c_num(obj); - sprintf(num_buf, "%lx", value); + sprintf(num_buf, num_fmt->hex, value); goto output_num; case 'X': obj = va_arg(vl, val); value = c_num(obj); - sprintf(num_buf, "%lX", value); + sprintf(num_buf, num_fmt->HEX, value); goto output_num; case 'o': obj = va_arg(vl, val); value = c_num(obj); - sprintf(num_buf, "%lo", value); + sprintf(num_buf, num_fmt->oct, value); goto output_num; case 'a': obj = va_arg(vl, val); @@ -816,7 +855,7 @@ val vformat(val stream, val fmtstr, va_list vl) goto premature; if (nump(obj)) { value = c_num(obj); - sprintf(num_buf, "%ld", value); + sprintf(num_buf, num_fmt->dec, value); goto output_num; } else if (stringp(obj)) { if (!vformat_str(stream, obj, width, left, precision)) @@ -831,7 +870,7 @@ val vformat(val stream, val fmtstr, va_list vl) goto premature; if (nump(obj)) { value = c_num(obj); - sprintf(num_buf, "%ld", value); + sprintf(num_buf, num_fmt->dec, value); if (!vformat_num(stream, num_buf, 0, 0, 0, 0)) return nil; continue; @@ -841,7 +880,8 @@ val vformat(val stream, val fmtstr, va_list vl) case 'p': ptr = va_arg(vl, void *); value = (int) ptr; - sprintf(num_buf, "0x%lx", value); + strcpy(num_buf, "0x"); + sprintf(num_buf + 2, num_fmt->hex, value); goto output_num; default: abort(); @@ -920,4 +960,5 @@ void stream_init(void) std_input = make_stdio_stream(stdin, string(L"stdin"), t, nil); std_output = make_stdio_stream(stdout, string(L"stdout"), nil, t); std_error = make_stdio_stream(stderr, string(L"stderr"), nil, t); + detect_format_string(); } @@ -33,6 +33,7 @@ #include <setjmp.h> #include <stdarg.h> #include <wchar.h> +#include "config.h" #include "lib.h" #include "stream.h" #include "gc.h" @@ -30,6 +30,7 @@ #include <setjmp.h> #include <dirent.h> #include <stdarg.h> +#include "config.h" #include "lib.h" #include "gc.h" #include "stream.h" @@ -148,7 +148,7 @@ noreturn val type_mismatch(val, ...); #define internal_error(STR) \ do { \ - extern obj_t *num(long); \ + extern obj_t *num(cnum); \ uw_throwf(internal_err, \ lit("~a:~a ~a"), \ lit(__FILE__), \ @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> #include <wchar.h> +#include "config.h" #include "lib.h" #include "utf8.h" |