autogen.ss
;; mzsocket: BSD/POSIX sockets library for mzscheme
;; Copyright (C) 2007 Dimitris Vyzovitis <vyzo@media.mit.edu>
;;
;; This library 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 2.1 of the License, or (at your option) any later version.
;;
;; This library 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 library; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
;; USA

(require (lib "plt-match.ss"))

(define header "// Autogenerated by autogen.ss")
(define sockopt.in "sockopt.in")
(define sockopt.export "sockopt.export")
(define sockopt.get "sockopt.get")
(define sockopt.set "sockopt.set")

(define (generate file gen)
  (let ((outp (open-output-file file 'truncate)))
    (parameterize ((current-output-port outp))
      (display header)
      (newline)
      (gen)
      (newline))
    (close-output-port outp)))

(define (generate-exports in)
  (define export "
          #ifdef ~a
          EXPORT_CONST( ~a );
          #endif
          ")

  (define (gen)
    (define (genx sym) (printf export sym sym))
    (for-each (match-lambda 
                (`(level ,sym . ,opts)
                 (for-each (match-lambda (`(,sym . ,_) (genx sym))) opts))
                (`(const . ,syms) (for-each genx syms)))
              in))

  (generate sockopt.export gen))

(define (generate-sockopts in)
  (define head "
          case ~a:
          switch (opt) {
          ")
  (define tail "
          default:
            FAIL( \"socket-~asockopt: unknown option\" );
          }
          ")
  (define sockopt "
          #ifdef ~a
          case ~a: ~aSOCKOPT_~a(~a);
          #endif
          ")
  
  (define (gen op)
    (define opname (string-upcase (symbol->string op)))
    (define (genx)
      (define (gen? optt) (or (eq? op optt) (eq? 'get/set optt)))
      (match-lambda
        (`(,sym (,type ,len) ,optt)
         (when (gen? optt)
           (printf sockopt sym sym opname type len)))
        (`(,sym ,type ,optt)
         (when (gen? optt)
           (printf sockopt sym sym opname type "")))))
    (lambda ()
      (for-each (match-lambda
                  (`(level ,level . ,opts)
                   (printf head level)
                   (for-each (genx) opts)
                   (printf tail opname))
                  (`(const . ,_) (void)))
                in)))

  (generate sockopt.get (gen 'get))
  (generate sockopt.set (gen 'set)))

(let ((in (read (open-input-file sockopt.in))))
  (generate-exports in)
  (generate-sockopts in))