#! ./scmlit \
- !#
;;;; "inc2scm", Convert numeric C #defines to Scheme definitions.
;; Copyright (C) 1991-1999 Free Software Foundation, Inc.
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU Lesser General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public
;; License along with this program. If not, see
;; .
;;; Author: Aubrey Jaffer.
(define (inc2scm.script args)
(cond ((< 1 (length args))
(apply scm<-usr/includes args))
(else (inc2scm.usage))))
(define (inc2scm.usage)
(display "\
\
Usage: inc2scm defines.scm [pre:] [/usr/include/] file1.h file2.h ...
\
Appends to DEFINES.SCM the Scheme translations of the numeric
#define statements in /USR/INCLUDE/FILE1.H, /USR/INCLUDE/FILE2.H, ...
PRE: is prepended to those scheme names lacking a prefix.
/USR/INCLUDE/ defaults to /usr/include/.
http://people.csail.mit.edu/jaffer/SCM
"
(current-error-port))
#f)
(require 'string-search)
(require 'printf)
(require 'scanf)
(define (StudlyCaps->dashed-name nstr)
(do ((idx (+ -1 (string-length nstr)) (+ -1 idx)))
((> 2 idx))
(cond ((and (char-upper-case? (string-ref nstr (+ -1 idx)))
(char-lower-case? (string-ref nstr idx)))
(set! nstr
(string-append (substring nstr 0 (+ -1 idx))
"-"
(substring nstr (+ -1 idx)
(string-length nstr)))))
((and (char-lower-case? (string-ref nstr (+ -1 idx)))
(char-upper-case? (string-ref nstr idx)))
(set! nstr
(string-append (substring nstr 0 idx)
"-"
(substring nstr idx
(string-length nstr)))))))
nstr)
;; SCHEMEIFY-NAME:
;; * Changes _ to -
;; * Changes the first - to : if it is within the first 3 characters.
;; * inserts dashes between `StudlyCaps'
(define (schemeify-name pre name)
(define nstr (string-subst name "_" "-"))
(let ((sid (string-index nstr #\-)))
(cond ((and sid (< sid 3)) (string-set! nstr sid #\:)
nstr)
(pre (string-append pre (StudlyCaps->dashed-name nstr)))
(else (StudlyCaps->dashed-name nstr)))))
(define (extract-defineds port)
(define sharp (string #\newline #\#))
(define defineds '())
(do ((find? (find-string-from-port? sharp port)
(find-string-from-port? sharp port)))
((not find?) (reverse defineds))
(do ((chr (read-char port) (read-char port)))
((or (eof-object? chr) (not (char-whitespace? chr)))
(and (eqv? chr #\d)
(let ((op #f) (va #f))
(fscanf port "efine%*[ \t]%s%*[ \t]%s" op va)
(if (and op va
(not (string-index op #\())
(not (eqv? #\_ (string-ref op 0)))
(not (equal? "int" va)))
(set! defineds (cons op defineds)))))))))
(define (scm<-includes scmname pre non-local? . filenames)
(define tmpprog "tmpprog")
(call-with-output-file (string-append tmpprog ".c")
(lambda (cport)
(for-each (lambda (filename)
(fprintf cport
(if non-local?
"#include <%s>\\n"
"#include \"%s\"\\n")
filename))
filenames)
(for-each
(lambda (args) (apply fprintf cport args))
`(("#include \\n")
("void pSl(sname, value)\\n")
(" char sname[];\\n")
(" int value;\\n")
("{\\n")
("%s\\n" " printf(\"(define %s %d)\\n\", sname, value);")
("}\\n")
("\\n")
("int main(argc, argv)\\n")
(" int argc;\\n")
(" char *argv[];\\n")
("{\\n")
))
(for-each
(lambda (filename)
(if non-local?
(set! filename (string-append non-local? filename)))
(fprintf cport "/* Extract #define values from %s */\\n" filename)
(fprintf cport "%s %s%s\\n"
" printf(\";;inc2scm extracted #define values from"
filename
"\\n\");")
(for-each
(lambda (name)
(fprintf cport "#ifdef %s\\n pSl(\"%s\", %s);\\n#endif\\n"
name (schemeify-name pre name) name))
(call-with-input-file filename extract-defineds)))
filenames)
(fprintf cport "}\\n")))
(cond
((not (zero? (system (sprintf #f "cc -o %s %s.c" tmpprog tmpprog)))))
((not (zero? (system (sprintf #f "./%s >> %s" tmpprog scmname)))))))
(define (scm<-usr/includes scmname . filenames)
(define pre (let ((first (car filenames)))
(cond ((substring-ci? ".h" first) #f)
(else (set! filenames (cdr filenames)) first))))
(define include-path "/usr/include/")
(let* ((first (car filenames)))
(cond ((memv (string-ref first (+ -1 (string-length first))) '(#\\ #\/))
(set! include-path first)
(set! filenames (cdr filenames)))))
(apply scm<-includes scmname pre include-path filenames)
(delete-file "tmpprog.c")
(delete-file "tmpprog"))
(define (scm<-h* scmname . filenames)
(define pre (let ((first (car filenames)))
(cond ((substring-ci? ".h" first) first)
(else (set! filenames (cdr filenames)) #f))))
(apply scm<-includes scmname pre #f filenames)
(delete-file "tmpprog.c")
(delete-file "tmpprog"))
(define h2scm scm<-h*)
;;; Local Variables:
;;; mode:scheme
;;; End:
(exit (inc2scm.script (list-tail *argv* *optind*)))