diff --git a/Makefile b/Makefile index 3aa63400..a10c3e0e 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,8 @@ all: chibi-scheme$(EXE) libs COMPILED_LIBS := lib/srfi/27/rand$(SO) lib/srfi/33/bit$(SO) \ lib/srfi/69/hash$(SO) lib/srfi/98/env$(SO) \ lib/chibi/ast$(SO) lib/chibi/net$(SO) \ - lib/chibi/posix$(SO) lib/chibi/heap-stats$(SO) + lib/chibi/filesystem$(SO) lib/chibi/process$(SO) \ + lib/chibi/time$(SO) lib/chibi/heap-stats$(SO) libs: $(COMPILED_LIBS) diff --git a/include/chibi/sexp.h b/include/chibi/sexp.h index 30c542bd..73c78efb 100644 --- a/include/chibi/sexp.h +++ b/include/chibi/sexp.h @@ -696,6 +696,7 @@ enum sexp_context_globals { SEXP_G_OOM_ERROR, /* out of memory exception object */ SEXP_G_OOS_ERROR, /* out of stack exception object */ SEXP_G_OPTIMIZATIONS, + SEXP_G_SIGNAL_HANDLERS, SEXP_G_CONFIG_ENV, SEXP_G_MODULE_PATH, SEXP_G_QUOTE_SYMBOL, diff --git a/lib/chibi/filesystem.module b/lib/chibi/filesystem.module new file mode 100644 index 00000000..fe0fbdcf --- /dev/null +++ b/lib/chibi/filesystem.module @@ -0,0 +1,22 @@ + +(define-module (chibi filesystem) + (export open-input-file-descriptor open-output-file-descriptor + duplicate-file-descriptor duplicate-file-descriptor-to + close-file-descriptor renumber-file-descriptor + delete-file link-file symbolic-link-file rename-file + directory-files create-directory delete-directory + file-status + file-device file-inode + file-mode file-num-links + file-owner file-group + file-represented-device file-size + file-block-size file-num-blocks + file-access-time file-modification-time file-change-time + file-regular? file-directory? file-character? + file-block? file-fifo? file-link? + file-socket? + ) + (import-immutable (scheme)) + (include-shared "filesystem") + (include "filesystem.scm")) + diff --git a/lib/chibi/filesystem.scm b/lib/chibi/filesystem.scm new file mode 100644 index 00000000..b3995221 --- /dev/null +++ b/lib/chibi/filesystem.scm @@ -0,0 +1,39 @@ + +(define (directory-fold dir kons knil) + (let ((dir (opendir dir))) + (let lp ((res knil)) + (let ((file (readdir dir))) + (if file (lp (kons (dirent-name file) res)) res))))) + +(define (directory-files dir) + (directory-fold dir cons '())) + +(define (renumber-file-descriptor old new) + (and (duplicate-file-descriptor-to old new) + (close-file-descriptor old))) + +(define (file-status file) + (if (string? file) (stat file) (fstat file))) + +(define (file-device x) (stat-dev (if (stat? x) x (file-status x)))) +(define (file-inode x) (stat-ino (if (stat? x) x (file-status x)))) +(define (file-mode x) (stat-mode (if (stat? x) x (file-status x)))) +(define (file-num-links x) (stat-nlinks (if (stat? x) x (file-status x)))) +(define (file-owner x) (stat-uid (if (stat? x) x (file-status x)))) +(define (file-group x) (stat-gid (if (stat? x) x (file-status x)))) +(define (file-represented-device x) (stat-rdev (if (stat? x) x (file-status x)))) +(define (file-size x) (stat-size (if (stat? x) x (file-status x)))) +(define (file-block-size x) (stat-blksize (if (stat? x) x (file-status x)))) +(define (file-num-blocks x) (stat-blocks (if (stat? x) x (file-status x)))) +(define (file-access-time x) (stat-atime (if (stat? x) x (file-status x)))) +(define (file-modification-time x) (stat-mtime (if (stat? x) x (file-status x)))) +(define (file-change-time x) (stat-ctime (if (stat? x) x (file-status x)))) + +(define (file-regular? x) (S_ISREG (file-mode x))) +(define (file-directory? x) (S_ISDIR (file-mode x))) +(define (file-character? x) (S_ISCHR (file-mode x))) +(define (file-block? x) (S_ISBLK (file-mode x))) +(define (file-fifo? x) (S_ISFIFO (file-mode x))) +(define (file-link? x) (S_ISLNK (file-mode x))) +(define (file-socket? x) (S_ISSOCK (file-mode x))) + diff --git a/lib/chibi/filesystem.stub b/lib/chibi/filesystem.stub new file mode 100644 index 00000000..ebd2f7be --- /dev/null +++ b/lib/chibi/filesystem.stub @@ -0,0 +1,88 @@ + +(c-system-include "sys/types.h") +(c-system-include "unistd.h") +(c-system-include "dirent.h") + +(define-c-struct DIR + finalizer: closedir) + +(define-c-struct dirent + (string d_name dirent-name)) + +(define-c-struct stat + predicate: stat? + (dev_t st_dev stat-dev) + (ino_t st_ino stat-ino) + (mode_t st_mode stat-mode) + (nlink_t st_nlink stat-nlinks) + (uid_t st_uid stat-uid) + (gid_t st_gid stat-gid) + (dev_t st_rdev stat-rdev) + (off_t st_size stat-size) + (blksize_t st_blksize stat-blksize) + (blkcnt_t st_blocks stat-blocks) + (time_t st_atime stat-atime) + (time_t st_mtime stat-mtime) + (time_t st_ctime stat-ctime)) + +(define-c boolean S_ISREG (mode_t)) +(define-c boolean S_ISDIR (mode_t)) +(define-c boolean S_ISCHR (mode_t)) +(define-c boolean S_ISBLK (mode_t)) +(define-c boolean S_ISFIFO (mode_t)) +(define-c boolean S_ISLNK (mode_t)) +(define-c boolean S_ISSOCK (mode_t)) + +;;(define-c-const int ("S_IFMT")) +(define-c-const int (file/socket "S_IFSOCK")) +(define-c-const int (file/link "S_IFLNK")) +(define-c-const int (file/regular "S_IFREG")) +(define-c-const int (file/block "S_IFBLK")) +(define-c-const int (file/directory "S_IFDIR")) +(define-c-const int (file/character "S_IFCHR")) +(define-c-const int (file/fifo "S_IFIFO")) +(define-c-const int (file/suid "S_ISUID")) +(define-c-const int (file/sgid "S_ISGID")) +(define-c-const int (file/sticky "S_ISVTX")) +;;(define-c-const int ("S_IRWXU")) +(define-c-const int (perm/user-read "S_IRUSR")) +(define-c-const int (perm/user-write "S_IWUSR")) +(define-c-const int (perm/user-execute "S_IXUSR")) +;;(define-c-const int ("S_IRWXG")) +(define-c-const int (perm/group-read "S_IRGRP")) +(define-c-const int (perm/group-write "S_IWGRP")) +(define-c-const int (perm/group-execute "S_IXGRP")) +;;(define-c-const int ("S_IRWXO")) +(define-c-const int (perm/others-read "S_IROTH")) +(define-c-const int (perm/others-write "S_IWOTH")) +(define-c-const int (perm/others-execute "S_IXOTH")) + +(define-c errno stat (string (result stat))) +(define-c errno fstat (int (result stat))) +(define-c errno (file-link-status "lstat") (string (result stat))) + +(define-c input-port (open-input-file-descriptor "fdopen") + (int (value "r" string))) +(define-c output-port (open-output-file-descriptor "fdopen") + (int (value "w" string))) + +(define-c errno (delete-file "unlink") (string)) +(define-c errno (link-file "link") (string string)) +(define-c errno (symbolic-link-file "symlink") (string string)) +(define-c errno (rename-file "rename") (string string)) + +(define-c non-null-string (current-directory "getcwd") + ((result (array char (auto-expand arg1))) (value 256 int))) + +(define-c errno (create-directory "mkdir") (string int)) +(define-c errno (delete-directory "rmdir") (string)) + +(define-c (free DIR) opendir (string)) +(define-c dirent readdir ((link DIR))) + +(define-c int (duplicate-file-descriptor "dup") (int)) +(define-c errno (duplicate-file-descriptor-to "dup2") (int int)) +(define-c errno (close-file-descriptor "close") (int)) + +(define-c errno (open-pipe "pipe") ((result (array int 2)))) +(define-c errno (make-fifo "mkfifo") (string (default #o644 int))) diff --git a/lib/chibi/posix.module b/lib/chibi/posix.module deleted file mode 100644 index af726ff4..00000000 --- a/lib/chibi/posix.module +++ /dev/null @@ -1,12 +0,0 @@ - -(define-module (chibi posix) - (export open-input-fd open-output-fd pipe - delete-file link-file symbolic-link-file rename-file - directory-files create-directory delete-directory - current-seconds - waitpid exit - ) - (import-immutable (scheme)) - (include-shared "posix") - (include "posix.scm")) - diff --git a/lib/chibi/posix.scm b/lib/chibi/posix.scm deleted file mode 100644 index ed5fa780..00000000 --- a/lib/chibi/posix.scm +++ /dev/null @@ -1,10 +0,0 @@ - -(define (directory-fold dir kons knil) - (let ((dir (opendir dir))) - (let lp ((res knil)) - (let ((file (readdir dir))) - (if file (lp (kons (dirent-name file) res)) res))))) - -(define (directory-files dir) - (directory-fold dir cons '())) - diff --git a/lib/chibi/posix.stub b/lib/chibi/posix.stub deleted file mode 100644 index 25dd5dbd..00000000 --- a/lib/chibi/posix.stub +++ /dev/null @@ -1,40 +0,0 @@ - -(c-system-include "sys/types.h") -(c-system-include "sys/wait.h") -(c-system-include "time.h") -(c-system-include "unistd.h") -(c-system-include "dirent.h") - -(define-c-struct DIR - finalizer: closedir) - -(define-c-struct dirent - (string d_name dirent-name)) - -(define-c input-port (open-input-fd "fdopen") (int (value "r" string))) -(define-c output-port (open-output-fd "fdopen") (int (value "w" string))) - -(define-c errno (delete-file "unlink") (string)) -(define-c errno (link-file "link") (string string)) -(define-c errno (symbolic-link-file "symlink") (string string)) -(define-c errno (rename-file "rename") (string string)) - -(define-c non-null-string (current-directory "getcwd") - ((result (array char (auto-expand arg1))) (value 256 int))) -(define-c errno (create-directory "mkdir") (string int)) -(define-c errno (delete-directory "rmdir") (string)) - -(define-c (free DIR) opendir (string)) -(define-c dirent readdir ((link DIR))) - -(define-c int (duplicate-fd "dup") (int)) - -(define-c pid_t fork ()) -(define-c pid_t waitpid (int (result int) int)) -(define-c void exit (int)) -(define-c int (execute execvp) (string (array string))) - -(define-c errno pipe ((result (array int 2)))) - -(define-c time_t (current-seconds "time") ((value NULL))) - diff --git a/lib/chibi/process.module b/lib/chibi/process.module new file mode 100644 index 00000000..3e3f2cdb --- /dev/null +++ b/lib/chibi/process.module @@ -0,0 +1,17 @@ + +(define-module (chibi process) + (export exit sleep fork kill execute waitpid + set-signal-action! make-signal-set signal-set-contains? + signal-set-fill! signal-set-add! signal-set-delete! + current-signal-mask + signal-mask-block! signal-mask-unblock! signal-mask-set! + signal/hang-up signal/interrupt signal/quit + signal/illegal signal/abort signal/fpe + signal/kill signal/segv signal/pipe + signal/alarm signal/term signal/user1 + signal/user2 signal/child signal/continue + signal/stop signal/tty-stop signal/tty-input + signal/tty-output) + (import-immutable (scheme)) + (include-shared "process")) + diff --git a/lib/chibi/process.stub b/lib/chibi/process.stub new file mode 100644 index 00000000..baa5a7a5 --- /dev/null +++ b/lib/chibi/process.stub @@ -0,0 +1,69 @@ + +(c-system-include "sys/types.h") +(c-system-include "sys/wait.h") +(c-system-include "signal.h") +(c-system-include "unistd.h") + +(define-c-struct siginfo + predicate: signal-info? + (int si_signo signal-number) + (int si_errno signal-error-number) + (int si_code signal-code) + (pid_t si_pid signal-pid) + (uid_t si_uid signal-uid) + (int si_status signal-status) + (clock_t si_utime signal-user-time) + (clock_t si_stime signal-system-time)) + +(define-c-type sigset_t + predicate: signal-set?) + +(define-c-const int (signal/hang-up "SIGHUP")) +(define-c-const int (signal/interrupt "SIGINT")) +(define-c-const int (signal/quit "SIGQUIT")) +(define-c-const int (signal/illegal "SIGILL")) +(define-c-const int (signal/abort "SIGABRT")) +(define-c-const int (signal/fpe "SIGFPE")) +(define-c-const int (signal/kill "SIGKILL")) +(define-c-const int (signal/segv "SIGSEGV")) +(define-c-const int (signal/pipe "SIGPIPE")) +(define-c-const int (signal/alarm "SIGALRM")) +(define-c-const int (signal/term "SIGTERM")) +(define-c-const int (signal/user1"SIGUSR1")) +(define-c-const int (signal/user2 "SIGUSR2")) +(define-c-const int (signal/child "SIGCHLD")) +(define-c-const int (signal/continue "SIGCONT")) +(define-c-const int (signal/stop "SIGSTOP")) +(define-c-const int (signal/tty-stop "SIGTSTP")) +(define-c-const int (signal/tty-input "SIGTTIN")) +(define-c-const int (signal/tty-output "SIGTTOU")) + +(c-include "signal.c") + +(define-c sexp (set-signal-action! "sexp_set_signal_action") + ((value ctx sexp) sexp sexp)) + +(define-c errno (make-signal-set "sigemptyset") ((result sigset_t))) +(define-c errno (signal-set-fill! "sigfillset") (sigset_t)) +(define-c errno (signal-set-add! "sigaddset") (sigset_t int)) +(define-c errno (signal-set-delete! "sigaddset") (sigset_t int)) +(define-c boolean (signal-set-contains? "sigismember") (sigset_t int)) + +(define-c errno (signal-mask-block! "sigprocmask") + ((value SIG_BLOCK int) sigset_t (value NULL sigset_t))) +(define-c errno (signal-mask-unblock! "sigprocmask") + ((value SIG_UNBLOCK int) sigset_t (value NULL sigset_t))) +(define-c errno (signal-mask-set! "sigprocmask") + ((value SIG_SETMASK int) sigset_t (value NULL sigset_t))) +(define-c errno (current-signal-mask "sigprocmask") + ((value SIG_BLOCK int) (value NULL sigset_t) (result sigset_t))) + +(define-c pid_t fork ()) +;;(define-c pid_t wait ((result int))) +(define-c pid_t waitpid (int (result int) int)) +(define-c errno kill (int int)) +;;(define-c errno raise (int)) +(define-c unsigned-int sleep (unsigned-int)) +(define-c void exit (int)) +(define-c int (execute execvp) (string (array string))) + diff --git a/lib/chibi/time.module b/lib/chibi/time.module new file mode 100644 index 00000000..84f2b800 --- /dev/null +++ b/lib/chibi/time.module @@ -0,0 +1,11 @@ + +(define-module (chibi time) + (export current-seconds get-time-of-day set-time-of-day! + seconds->time seconds->string time->seconds time->string + timeval-seconds timeval-microseconds + timezone-offset timezone-dst-time + time-second time-minute time-hour time-day time-month time-year + time-day-of-week time-day-of-year time-dst?) + (import-immutable (scheme)) + (include-shared "time")) + diff --git a/lib/chibi/time.stub b/lib/chibi/time.stub new file mode 100644 index 00000000..b2d444a8 --- /dev/null +++ b/lib/chibi/time.stub @@ -0,0 +1,45 @@ + +(c-system-include "time.h") +(c-system-include "sys/time.h") + +(define-c-struct tm + (int tm_sec time-second) + (int tm_min time-minute) + (int tm_hour time-hour) + (int tm_mday time-day) + (int tm_mon time-month) + (int tm_year time-year) + (int tm_wday time-day-of-week) + (int tm_yday time-day-of-year) + (int tm_isdst time-dst?)) + +(define-c-struct timeval + predicate: timeval? + (time_t tv_sec timeval-seconds) + (int tv_usec timeval-microseconds)) + +(define-c-struct timezone + predicate: timezone? + (int tz_minuteswest timezone-offset) + (int tz_dsttime timezone-dst-time)) + +(define-c time_t (current-seconds "time") ((value NULL))) + +(define-c errno (get-time-of-day "gettimeofday") + ((result timeval) (result timezone))) + +(define-c errno (set-time-of-day! "settimeofday") + ((maybe-null timeval) (maybe-null default NULL timezone))) + +(define-c non-null-pointer (seconds->time "localtime_r") + ((pointer time_t) (result tm))) + +(define-c time_t (time->seconds "mktime") + (tm)) + +(define-c non-null-string (seconds->string "ctime_r") + ((pointer time_t) (result (array char 64)))) + +(define-c non-null-string (time->string "asctime_r") + (tm (result (array char 64)))) + diff --git a/lib/srfi/1.module b/lib/srfi/1.module index 8d341b6b..3d3da044 100644 --- a/lib/srfi/1.module +++ b/lib/srfi/1.module @@ -18,7 +18,7 @@ lset<= lset= lset-adjoin lset-union lset-union! lset-intersection lset-intersection! lset-difference lset-difference! lset-xor lset-xor! lset-diff+intersection lset-diff+intersection!) - (import-immutable (scheme)) + (import (scheme)) (include "1/predicates.scm" "1/selectors.scm" "1/search.scm" diff --git a/tools/genstubs.scm b/tools/genstubs.scm index 9f33ef91..c679c30c 100755 --- a/tools/genstubs.scm +++ b/tools/genstubs.scm @@ -139,6 +139,7 @@ (define *types* '()) (define *funcs* '()) +(define *consts* '()) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; type objects @@ -202,10 +203,12 @@ ;; type predicates (define (signed-int-type? type) - (memq type '(signed-char short int long))) + (memq type '(signed-char short int long boolean))) (define (unsigned-int-type? type) - (memq type '(unsigned-char unsigned-short unsigned-int unsigned-long size_t pid_t))) + (memq type '(unsigned-char unsigned-short unsigned-int unsigned-long + size_t off_t time_t clock_t dev_t ino_t mode_t nlink_t + uid_t gid_t pid_t blksize_t blkcnt_t sigval_t))) (define (int-type? type) (or (signed-int-type? type) (unsigned-int-type? type))) @@ -214,14 +217,23 @@ (memq type '(float double long-double long-long-double))) (define (string-type? type) - (memq type '(char* string env-string non-null-string))) + (or (memq type '(char* string env-string non-null-string)) + (and (vector? type) + (type-array type) + (not (type-pointer? type)) + (eq? 'char (type-base type))))) (define (error-type? type) - (memq type '(errno non-null-string))) + (memq type '(errno non-null-string non-null-pointer))) (define (array-type? type) (and (type-array type) (not (eq? 'char (type-base type))))) +(define (basic-type? type) + (let ((type (parse-type type))) + (and (not (type-array type)) + (not (assq (type-base type) *types*))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; function objects @@ -250,7 +262,7 @@ (cond ((type-result? type) (lp (cdr ls) (+ i 1) (cons type results) (cons type c-args) s-args)) - ((type-value type) + ((and (type-value type) (not (type-default? type))) (lp (cdr ls) (+ i 1) results (cons type c-args) s-args)) (else (lp (cdr ls) (+ i 1) results (cons type c-args) (cons type s-args))) @@ -303,10 +315,8 @@ (define (collect) (if (= i from) res (cons (substring str from i) res))) (cond ((>= i len) (string-concatenate-reverse (collect))) - ((eqv? c (string-ref str i)) - (lp (+ i 1) (+ i 1) (cons r (collect)))) - (else - (lp from (+ i 1) res)))))) + ((eqv? c (string-ref str i)) (lp (+ i 1) (+ i 1) (cons r (collect)))) + (else (lp from (+ i 1) res)))))) (define (string-scan c str . o) (let ((limit (string-length str))) @@ -349,9 +359,21 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; naming +(define (c-char? c) + (or (char-alphabetic? c) (char-numeric? c) (memv c '(#\_ #\- #\! #\?)))) + +(define (c-escape str) + (let ((len (string-length str))) + (let lp ((from 0) (i 0) (res '())) + (define (collect) (if (= i from) res (cons (substring str from i) res))) + (cond + ((>= i len) (string-concatenate-reverse (collect))) + ((not (c-char? (string-ref str i))) (lp (+ i 1) (+ i 1) (cons "_" (cons (number->string (char->integer (string-ref str i)) 16) (collect))))) + (else (lp from (+ i 1) res)))))) + (define (mangle x) (string-replace - (string-replace (string-replace (x->string x) #\- "_") #\? "_p") + (string-replace (string-replace (c-escape (x->string x)) #\- "_") #\? "_p") #\! "_x")) (define (generate-stub-name sym) @@ -367,20 +389,38 @@ (apply cat args) (newline)) +(define (c-include header) + (cat "\n#include \"" header "\"\n")) + (define (c-system-include header) (cat "\n#include <" header ">\n")) +(define (parse-struct-like ls) + (map (lambda (x) (if (pair? x) (cons (parse-type (car x)) (cdr x)) x)) ls)) + +(define-syntax define-struct-like + (er-macro-transformer + (lambda (expr rename compare) + (set! *types* + `((,(cadr expr) + ,@(parse-struct-like (cddr expr))) + ,@*types*)) + `(cat "\nstatic sexp_uint_t " ,(type-id-name (cadr expr)) ";\n")))) + (define-syntax define-c-struct (er-macro-transformer (lambda (expr rename compare) - (set! *types* - (cons (map (lambda (x) - (if (pair? x) - (cons (parse-type (car x)) (cdr x)) - x)) - (cdr expr)) - *types*)) - `(cat "\nstatic sexp_uint_t " ,(type-id-name (cadr expr)) ";\n")))) + `(define-struct-like ,(cadr expr) type: struct ,@(cddr expr))))) + +(define-syntax define-c-class + (er-macro-transformer + (lambda (expr rename compare) + `(define-struct-like ,(cadr expr) type: class ,@(cddr expr))))) + +(define-syntax define-c-type + (er-macro-transformer + (lambda (expr rename compare) + `(define-struct-like ,(cadr expr) ,@(cddr expr))))) (define-syntax define-c (er-macro-transformer @@ -388,6 +428,12 @@ (set! *funcs* (cons (parse-func (cdr expr)) *funcs*)) #f))) +(define-syntax define-c-const + (er-macro-transformer + (lambda (expr rename compare) + (set! *consts* + (cons (cons (parse-type (cadr expr)) (cddr expr)) *consts*))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; C code generation @@ -398,6 +444,8 @@ (cat "((" val "), SEXP_VOID)")) ((or (eq? base 'sexp) (error-type? base)) (cat val)) + ((eq? base 'boolean) + (cat "sexp_make_boolean(" val ")")) ((eq? base 'time_t) (cat "sexp_make_integer(ctx, sexp_shift_epoch(" val "))")) ((int-type? base) @@ -422,7 +470,11 @@ (ctype (cat "sexp_make_cpointer(ctx, " (type-id-name base) ", " val ", " (or (and (pair? o) (car o)) "SEXP_FALSE") ", " - (if (type-free? type) 1 0) ")")) + (if (or (type-free? type) + (and (type-result? type) (not (basic-type? type)))) + 1 + 0) + ")")) (else (error "unknown type" base)))))))) @@ -432,8 +484,10 @@ (cond ((eq? base 'sexp) (cat val)) + ((eq? base 'boolean) + (cat "sexp_truep(" val ")")) ((eq? base 'time_t) - (cat "sexp_uint_value(sexp_unshift_epoch(" val "))")) + (cat "sexp_unshift_epoch(sexp_uint_value(" val "))")) ((signed-int-type? base) (cat "sexp_sint_value(" val ")")) ((unsigned-int-type? base) @@ -462,6 +516,7 @@ ((float-type? base) "sexp_flonump") ((string-type? base) "sexp_stringp") ((eq? base 'char) "sexp_charp") + ((eq? base 'boolean) "sexp_booleanp") (else #f)))) (define (type-name type) @@ -469,6 +524,7 @@ (cond ((int-type? base) "integer") ((float-type? base) "flonum") + ((eq? 'boolean base) "int") (else base)))) (define (base-type-c-name base) @@ -479,12 +535,15 @@ (define (type-c-name type) (let* ((type (parse-type type)) (base (type-base type)) - (struct? (assq base *types*))) + (type-spec (assq base *types*)) + (struct-type + (cond ((and type-spec (memq 'type: type-spec)) => cadr) + (else #f)))) (string-append (if (type-const? type) "const " "") - (if struct? "struct " "") + (if struct-type (string-append (symbol->string struct-type) " ") "") (string-replace (base-type-c-name base) #\- " ") - (if struct? "*" "") + (if type-spec "*" "") (if (type-pointer? type) "*" "")))) (define (check-type arg type) @@ -515,7 +574,7 @@ (array (type-array type)) (base-type (type-base type))) (cond - (array + ((and array (not (string-type? type))) (cond ((number? array) (cat " if (!sexp_listp(ctx, " arg ")" @@ -544,9 +603,11 @@ " if (! " (lambda () (check-type arg type)) ")\n" " return sexp_type_exception(ctx, \"not " (definite-article (type-name type)) "\", " arg ");\n")) + ((eq? 'sexp base-type)) + ((string-type? type) + (write-validator arg 'string)) (else - (if (not (eq? 'sexp (type-base type))) - (display "WARNING: don't know how to validate: " (current-error-port))) + (display "WARNING: don't know how to validate: " (current-error-port)) (write type (current-error-port)) (newline (current-error-port)) (write type))))))) @@ -588,7 +649,9 @@ (gc-vars (if preserve-res? (cons "res" gc-vars) gc-vars)) (sexps (if preserve-res? '() '("res"))) (num-gc-vars (length gc-vars)) - (ints (if (or return-res? (eq? 'non-null-string (type-base ret-type))) + (ints (if (or return-res? + (memq (type-base ret-type) + '(non-null-string non-null-pointer))) '() '("err"))) (ints (if (or (array-type? ret-type) @@ -596,8 +659,9 @@ (any array-type? scheme-args)) (cons "i" ints) ints))) - (if(eq? 'non-null-string (type-base ret-type)) - (cat " char *err;\n")) + (case (type-base ret-type) + ((non-null-string) (cat " char *err;\n")) + ((non-null-pointer) (cat " void *err;\n"))) (cond ((pair? ints) (cat " int " (car ints)) @@ -624,6 +688,13 @@ (append (if (type-array ret-type) (list ret-type) '()) results (remove type-result? (filter type-array scheme-args)))) + (for-each + (lambda (arg) + (cond + ((and (type-pointer? arg) (basic-type? arg)) + (cat " " (type-c-name (type-base arg)) + " tmp" (type-index arg) ";\n")))) + scheme-args) (cond ((pair? sexps) (cat " sexp " (car sexps)) @@ -657,7 +728,7 @@ ";\n" " tmp" (type-index a) " = buf" (type-index a) ";\n")))) (cond - ((and (not (type-result? a)) (type-array a)) + ((and (not (type-result? a)) (type-array a) (not (string-type? a))) (if (not (number? (type-array a))) (cat " tmp" (type-index a) " = (" (type-c-name (type-base a)) "*) malloc(" @@ -670,9 +741,45 @@ ";\n" " }\n") (if (not (number? (type-array a))) - (cat " tmp" (type-index a) "[i] = NULL;\n"))))) + (cat " tmp" (type-index a) "[i] = NULL;\n"))) + ((and (type-result? a) (not (basic-type? a)) + (not (type-free? a)) (not (type-auto-expand? a)) + (or (not (type-array a)) + (not (integer? (get-array-length func a))))) + (cat " tmp" (type-index a) " = malloc(sizeof(tmp" (type-index a) + "[0]));\n")) + ((and (type-pointer? a) (basic-type? a)) + (cat " tmp" (type-index a) " = " + (lambda () + (scheme->c-converter + a + (string-append "arg" (type-index-string a)))) + ";\n")))) (func-c-args func))) +(define (write-actual-parameter func arg) + (cond + ((and (not (type-default? arg)) (type-value arg)) + => (lambda (x) + (cond + ((any (lambda (y) + (and (type-array y) + (eq? x (get-array-length func y)))) + (func-c-args func)) + => (lambda (y) (cat "len" (type-index y)))) + (else (write x))))) + ((or (type-result? arg) (type-array arg)) + (cat (if (or (type-pointer? arg) (type-free? arg) (basic-type? arg)) + "&" + "") + "tmp" (type-index arg))) + ((and (type-pointer? arg) (basic-type? arg)) + (cat "&tmp" (type-index arg))) + (else + (scheme->c-converter + arg + (string-append "arg" (type-index-string arg)))))) + (define (write-call func) (let ((ret-type (func-ret-type func)) (c-name (func-c-name func)) @@ -691,23 +798,7 @@ (for-each (lambda (arg) (if (> (type-index arg) 0) (cat ", ")) - (cond - ((or (type-result? arg) (type-array arg)) - (cat (if (or (type-pointer? arg) (type-array arg)) "" "&") - "tmp" (type-index arg))) - ((type-value arg) - => (lambda (x) - (cond - ((any (lambda (y) - (and (type-array y) - (eq? x (get-array-length func y)))) - (func-c-args func)) - => (lambda (y) (cat "len" (type-index y)))) - (else (write x))))) - (else - (scheme->c-converter - arg - (string-append "arg" (type-index-string arg)))))) + (write-actual-parameter func arg)) c-args) (cat ")")) (cond @@ -762,7 +853,10 @@ (results (func-results func))) (if error-res? (cat " if (" - (if (eq? 'non-null-string (type-base (func-ret-type func))) "!" "") + (if (memq (type-base (func-ret-type func)) + '(non-null-string non-null-pointer)) + "!" + "") "err) {\n" (cond ((any type-auto-expand? (func-c-args func)) @@ -847,10 +941,21 @@ "}\n\n")) (define (write-func-binding func) - (cat " sexp_define_foreign(ctx, env, " - (lambda () (write (symbol->string (func-scheme-name func)))) - ", " (length (func-scheme-args func)) ", " - (func-stub-name func) ");\n")) + (let ((default (and (pair? (func-scheme-args func)) + (type-default? (car (reverse (func-scheme-args func)))) + (car (reverse (func-scheme-args func)))))) + (cat (if default + " sexp_define_foreign_opt(ctx, env, " + " sexp_define_foreign(ctx, env, ") + (lambda () (write (symbol->string (func-scheme-name func)))) + ", " (length (func-scheme-args func)) ", " + (func-stub-name func) + (if default ", " "") + (if default + (lambda () + (c->scheme-converter default (type-value default))) + "") + ");\n"))) (define (write-type type) (let ((name (car type)) @@ -975,6 +1080,13 @@ *funcs*))))))) type))) +(define (write-const const) + (let ((scheme-name (if (pair? (cadr const)) (caadr const) (cadr const))) + (c-name (if (pair? (cadr const)) (cadadr const) (mangle (cadr const))))) + (cat " name = sexp_intern(ctx, \"" scheme-name "\");\n" + " sexp_env_define(ctx, env, name, tmp=" + (lambda () (c->scheme-converter (car const) c-name)) ");\n"))) + (define (write-utilities) (define (input-env-string? x) (and (eq? 'env-string (type-base x)) (not (type-result? x)))) @@ -1001,6 +1113,7 @@ (cat "sexp sexp_init_library (sexp ctx, sexp env) {\n" " sexp_gc_var2(name, tmp);\n" " sexp_gc_preserve2(ctx, name, tmp);\n") + (for-each write-const *consts*) (for-each write-type *types*) (for-each write-func-binding *funcs*) (cat " sexp_gc_release2(ctx);\n"