341 lines
13 KiB
Plaintext
341 lines
13 KiB
Plaintext
|
(define c-output #f)
|
||
|
(define sch-output #f)
|
||
|
|
||
|
(define (select-functions)
|
||
|
(do ((functions functions (cdr functions)))
|
||
|
((null? functions))
|
||
|
(referenced! (car functions))))
|
||
|
|
||
|
(define (generate-translation)
|
||
|
(delete-file "C-OUTPUT")
|
||
|
(delete-file "SCH-OUTPUT")
|
||
|
(set! c-output (open-output-file "C-OUTPUT"))
|
||
|
(set! sch-output (open-output-file "SCH-OUTPUT"))
|
||
|
(display "#include \"chez-stdlib.h\"" c-output) (newline c-output)
|
||
|
(display "#include \"stdlib.h\"" c-output) (newline c-output)
|
||
|
|
||
|
(dump-structs)
|
||
|
(dump-unions)
|
||
|
(dump-functions)
|
||
|
(dump-variables)
|
||
|
(dump-enums)
|
||
|
(dump-macros)
|
||
|
|
||
|
(close-output-port c-output)
|
||
|
(close-output-port sch-output)
|
||
|
|
||
|
#t)
|
||
|
|
||
|
(define (chez-type type)
|
||
|
(case (record-tag type)
|
||
|
((pointer) 'unsigned-32)
|
||
|
((int long enum) 'integer-32)
|
||
|
((unsigned unsigned-long) 'unsigned-32)
|
||
|
((char unsigned-char signed-char) 'char)
|
||
|
((void) 'void)
|
||
|
((double) 'double-float)
|
||
|
((float) 'single-float)
|
||
|
((***invalid***) '***invalid***)
|
||
|
(else
|
||
|
(warn "Cannot translate this type: " type)
|
||
|
(string->symbol (string-append (symbol->string '***invalid:)
|
||
|
(symbol->string (record-tag type))
|
||
|
"***")))))
|
||
|
|
||
|
(define (dump-structs)
|
||
|
(dump-struct/union structs struct-names "struct"))
|
||
|
|
||
|
(define (dump-unions)
|
||
|
(dump-struct/union unions union-names "union"))
|
||
|
(define (dump-struct/union records typedef-name-getter qualifier)
|
||
|
(for-each
|
||
|
(lambda (structure)
|
||
|
(if (referenced? structure)
|
||
|
(begin
|
||
|
(if (user-defined-tag? (tag structure))
|
||
|
(dump-struct/union-def structure qualifier (tag structure)))
|
||
|
(for-each (lambda (n)
|
||
|
(if (user-defined-tag? (tag structure))
|
||
|
(generate-reference-to-structure structure n qualifier)
|
||
|
(dump-struct/union-def structure "" n)))
|
||
|
(typedef-name-getter structure)))))
|
||
|
records))
|
||
|
(define (generate-reference-to-structure structure typedef-name qualifier)
|
||
|
(for-each (lambda (n)
|
||
|
(let ((newname (compute-newname n typedef-name (tag structure) qualifier)))
|
||
|
(display `(define ,newname ,n) sch-output)
|
||
|
(newline sch-output)))
|
||
|
(cached-names structure)))
|
||
|
(define (compute-newname oldname typedef-name tag qualifier)
|
||
|
(let ((q (string-append qualifier "_" tag)))
|
||
|
(let ((get (string-append "_get_" q))
|
||
|
(set (string-append "_set_" q))
|
||
|
(alloc (string-append "_alloc_" q))
|
||
|
(free (string-append "_free_" q)))
|
||
|
(cond ((string-prefix=? oldname get)
|
||
|
(string-append "_get_" typedef-name (substring oldname (string-length get)
|
||
|
(string-length oldname))))
|
||
|
((string-prefix=? oldname set)
|
||
|
(string-append "_set_" typedef-name (substring oldname (string-length set)
|
||
|
(string-length oldname))))
|
||
|
((string-prefix=? oldname alloc) (string-append "_alloc_" typedef-name))
|
||
|
((string-prefix=? oldname free) (string-append "_free_" typedef-name))
|
||
|
(else (error "compute-newname: can't handle: " oldname))))))
|
||
|
(define (dump-struct/union-def structure qualifier name)
|
||
|
(let* ((funcname (if (string=? qualifier "")
|
||
|
name
|
||
|
(string-append qualifier "_" name)))
|
||
|
(cast (if (string=? qualifier "")
|
||
|
name
|
||
|
(string-append qualifier " " name))))
|
||
|
(generate-constructor-and-destructor structure funcname cast)
|
||
|
(generate-accessors-and-mutators structure funcname cast "")))
|
||
|
(define (generate-constructor-and-destructor structure funcname cast)
|
||
|
(function-pair constructor-template
|
||
|
(vector funcname cast)
|
||
|
(string-append "_alloc_" funcname)
|
||
|
'((void ()))
|
||
|
`(pointer ,(struct/union-ref structure)))
|
||
|
(function-pair destructor-template
|
||
|
(vector funcname cast)
|
||
|
(string-append "_free_" funcname)
|
||
|
`((pointer ,(struct/union-ref structure)))
|
||
|
'(void ()))
|
||
|
(cache-name structure (string-append "_alloc_" funcname))
|
||
|
(cache-name structure (string-append "_free_" funcname)))
|
||
|
(define constructor-template
|
||
|
"unsigned _alloc_@0(void) {
|
||
|
@1 *_p = (@1 *)malloc(sizeof(@1)); return (_p == 0 ? 0 : (unsigned)_p);
|
||
|
}")
|
||
|
|
||
|
(define destructor-template
|
||
|
"void _free_@0(unsigned _p) { if (_p == 0) abort(); free((@1 *)_p); }")
|
||
|
(define (generate-accessors-and-mutators structure funcname cast selector)
|
||
|
(for-each
|
||
|
(lambda (field)
|
||
|
(let ((funcname (string-append funcname "_" (canonical-name (name field))))
|
||
|
(selector (string-append selector (if (string=? selector "") "" ".") (name field))))
|
||
|
(cond ((basic-type? (type field))
|
||
|
(getset-basic-type structure funcname cast selector field))
|
||
|
((array-type? (type field))
|
||
|
(getset-array-type structure funcname cast selector field))
|
||
|
((structured-type? (type field))
|
||
|
(getset-structured-type structure funcname cast selector field))
|
||
|
(else (error 'generate-accessors-and-mutators "Unknown: " field)))))
|
||
|
(fields structure)))
|
||
|
(define (getset-basic-type struct funcname cast selector field)
|
||
|
(let* ((typename (basic-type-name (type field)))
|
||
|
(fieldtype (c-cast-expression (type field))))
|
||
|
(function-pair accessor-template
|
||
|
(vector typename funcname cast selector)
|
||
|
(string-append "_get_" funcname)
|
||
|
`((pointer ,(struct/union-ref struct)))
|
||
|
(type field))
|
||
|
(function-pair mutator-template
|
||
|
(vector typename funcname cast selector fieldtype)
|
||
|
(string-append "_set_" funcname)
|
||
|
`((pointer ,(struct/union-ref struct)) ,(type field))
|
||
|
`(void ()))
|
||
|
(cache-name struct (string-append "_get_" funcname))
|
||
|
(cache-name struct (string-append "_set_" funcname))))
|
||
|
(define accessor-template
|
||
|
"@0 _get_@1( unsigned _p ) { return (@0)((@2*)_p)->@3; }")
|
||
|
|
||
|
(define mutator-template
|
||
|
"void _set_@1( unsigned _p, @0 _v ) { ((@2*)_p)->@3 = (@4)_v; }")
|
||
|
(define (getset-array-type structure funcname cast selector field)
|
||
|
(function-pair array-accessor-template
|
||
|
(vector funcname cast selector)
|
||
|
(string-append "_get_" funcname)
|
||
|
`((pointer ,(struct/union-ref structure)))
|
||
|
'(unsigned))
|
||
|
(cache-name structure (string-append "_get_" funcname)))
|
||
|
|
||
|
(define array-accessor-template
|
||
|
"unsigned _get_@0( unsigned _p ) { return (unsigned)(((@1*)_p)->@2); }")
|
||
|
(define (getset-structured-type structure funcname cast selector field)
|
||
|
(let (;(selector (string-append selector "." (name field)))
|
||
|
;(funcname (string-append funcname "_" (canonical-name (name field))))
|
||
|
(struct (if (eq? (record-tag (type field)) 'struct-ref)
|
||
|
(lookup (tag (type field)) structs)
|
||
|
(lookup (tag (type field)) unions))))
|
||
|
(generate-accessors-and-mutators struct funcname cast selector)))
|
||
|
|
||
|
(define (dump-variables)
|
||
|
(for-each (lambda (v)
|
||
|
(let ((n (canonical-name (name v))))
|
||
|
(function-pair global-template
|
||
|
(vector n (name v))
|
||
|
(string-append "_glob_" n)
|
||
|
'((void ()))
|
||
|
`(pointer ,(type v)))))
|
||
|
vars))
|
||
|
|
||
|
(define global-template
|
||
|
"unsigned _glob_@0( void ) { return (unsigned)&@1; }")
|
||
|
|
||
|
(define (dump-functions)
|
||
|
(for-each (lambda (f) (define-foreign (name f) (type f)))
|
||
|
functions))
|
||
|
(define (define-foreign name type)
|
||
|
(let ((argtypes (arglist type))
|
||
|
(returntype (rett type)))
|
||
|
(let loop ((l argtypes))
|
||
|
(cond ((null? l) #t)
|
||
|
((structured-type? (car l))
|
||
|
(warn "Cannot pass structured value of type"
|
||
|
(rational-typename (car l))
|
||
|
"to function"
|
||
|
name)
|
||
|
(set-car! l '(***invalid***))
|
||
|
(loop (cdr l)))
|
||
|
(else
|
||
|
(loop (cdr l)))))
|
||
|
(if (structured-type? returntype)
|
||
|
(begin (warn "Cannot receive structured value of type"
|
||
|
(rational-typename returntype)
|
||
|
"from function"
|
||
|
name)
|
||
|
(set! returntype '(***invalid***))))
|
||
|
|
||
|
(write
|
||
|
`(define ,(string->symbol (canonical-name name))
|
||
|
(foreign-function ,name
|
||
|
,(chez-map-args argtypes name)
|
||
|
,(chez-type returntype)))
|
||
|
sch-output)
|
||
|
(newline sch-output)))
|
||
|
(define (chez-map-args args name)
|
||
|
(cond ((and (= (length args) 1)
|
||
|
(eq? (caar args) 'void))
|
||
|
'())
|
||
|
((= (length args) 0)
|
||
|
(warn "Function without prototype assumed to take no arguments:"
|
||
|
name)
|
||
|
'())
|
||
|
(else
|
||
|
(map (lambda (x)
|
||
|
(if (eq? (record-tag x) 'void)
|
||
|
(begin (warn "Varargs *cannot* be handled for" name)
|
||
|
'***invalid***)
|
||
|
(chez-type x)))
|
||
|
args))))
|
||
|
|
||
|
(define (dump-enums)
|
||
|
(for-each (lambda (x)
|
||
|
(display (instantiate "(define @0 @1)"
|
||
|
(vector (canonical-name (name x))
|
||
|
(number->string (value x))))
|
||
|
sch-output)
|
||
|
(newline sch-output))
|
||
|
enum-idents))
|
||
|
|
||
|
(define (dump-macros)
|
||
|
(for-each (lambda (m)
|
||
|
(if (and (valid-ident? (name m))
|
||
|
(valid-number? (value m)))
|
||
|
(begin
|
||
|
(display `(define ,(canonical-name (name m))
|
||
|
,(evaluate-number (value m)))
|
||
|
sch-output)
|
||
|
(newline sch-output))))
|
||
|
macros))
|
||
|
(define (valid-ident? s)
|
||
|
(andmap (lambda (c)
|
||
|
(or (char-upper-case? c)
|
||
|
(char-lower-case? c)
|
||
|
(char-numeric? c)
|
||
|
(char=? c #\_)))
|
||
|
(string->list s)))
|
||
|
|
||
|
(define (valid-number? s)
|
||
|
(let ((n (evaluate-number s)))
|
||
|
n))
|
||
|
|
||
|
(define (function-pair c-template template-args scheme-name arglist rett)
|
||
|
(display (instantiate c-template template-args) c-output)
|
||
|
(newline c-output)
|
||
|
(define-foreign scheme-name
|
||
|
`(function ,arglist ,rett)))
|
||
|
(define (basic-type-name type)
|
||
|
(let ((probe (assq (record-tag type)
|
||
|
'((char . "char")
|
||
|
(signed-char . "signed char")
|
||
|
(unsigned-char . "unsigned char")
|
||
|
(short . "short")
|
||
|
(unsigned-short "unsigned short")
|
||
|
(int . "int")
|
||
|
(enum . "int")
|
||
|
(unsigned . "unsigned")
|
||
|
(long . "long")
|
||
|
(unsigned-long . "unsigned long")
|
||
|
(void . "void")
|
||
|
(pointer . "unsigned")
|
||
|
(float . "float")
|
||
|
(double . "double")
|
||
|
))))
|
||
|
(if probe
|
||
|
(cdr probe)
|
||
|
(begin (warn "Unknown type " type)
|
||
|
"***invalid***"))))
|
||
|
(define (c-cast-expression type)
|
||
|
(cond ((primitive-type? type)
|
||
|
(basic-type-name type))
|
||
|
((pointer-type? type)
|
||
|
(string-append (c-cast-expression (cadr type)) "*"))
|
||
|
((eq? (record-tag type) 'enum-ref)
|
||
|
(basic-type-name '(int ())))
|
||
|
((memq (record-tag type) '(struct-ref union-ref))
|
||
|
(let ((t (tag type)))
|
||
|
(if (user-defined-tag? t)
|
||
|
(string-append (if (eq? (record-tag type) 'struct-ref)
|
||
|
"struct "
|
||
|
"union ")
|
||
|
t)
|
||
|
(let ((names (if (eq? (record-tag type) 'struct-ref)
|
||
|
(struct-names type)
|
||
|
(union-names type))))
|
||
|
(if (= (length names) 1)
|
||
|
(car names)
|
||
|
(error "c-cast-expression: bad: " type))))))
|
||
|
(else
|
||
|
(warn "c-cast-expression: Too complicated: " type)
|
||
|
"unknown")))
|
||
|
(define (string-prefix=? s prefix)
|
||
|
(let ((limit (string-length prefix)))
|
||
|
(and (<= limit (string-length s))
|
||
|
(let loop ((i 0))
|
||
|
(or (= i limit)
|
||
|
(and (char=? (string-ref s i) (string-ref prefix i))
|
||
|
(loop (+ i 1))))))))
|
||
|
(define (rational-typename type)
|
||
|
(case (record-tag type)
|
||
|
((struct-ref)
|
||
|
(if (user-defined-tag? (tag type))
|
||
|
type
|
||
|
(let ((t (lookup (tag type) structs)))
|
||
|
(if (not t)
|
||
|
type
|
||
|
(list 'struct-ref (tag t))))))
|
||
|
((union-ref)
|
||
|
(if (user-defined-tag? (tag type))
|
||
|
type
|
||
|
(let ((t (lookup (tag type) unions)))
|
||
|
(if (not t)
|
||
|
type
|
||
|
(list 'union-ref (tag t))))))
|
||
|
(else type)))
|
||
|
(define (evaluate-number s)
|
||
|
(let ((k (string->list s)))
|
||
|
(cond ((null? k) #f)
|
||
|
((not (char-numeric? (car k))) #f)
|
||
|
((char=? (car k) #\0)
|
||
|
(cond ((null? (cdr k)) 0)
|
||
|
((or (char=? (cadr k) #\x) (char=? (cadr k) #\X))
|
||
|
(string->number (list->string (cddr k)) 16))
|
||
|
(else
|
||
|
(string->number s 8))))
|
||
|
(else
|
||
|
(string->number s)))))
|
||
|
|