;;;;
;;;; make-C-boot.stk            -- Create a C image to boot on
;;;;
;;;; Copyright © 2005-2024 Erick Gallesio <eg@stklos.net>
;;;;
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation; either version 2 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 General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
;;;; USA.
;;;;
;;;;           Author: Erick Gallesio [eg@essi.fr]
;;;;    Creation date: 29-Mar-2005 14:58 (eg)
;;;;

;; ----------------------------------------------------------------------
;;      header ...
;; ----------------------------------------------------------------------
(define (header in out)
  (format out "/*
This file was automatically generated by make-C-boot
This is a dump of the image in file ~A
***DO NOT EDIT BY HAND***
*/

#include \"stklos.h\"\n\n" (port-file-name in)))

;; ----------------------------------------------------------------------
;;      write-boot-file ...
;; ----------------------------------------------------------------------
(define (write-boot-file src dst)
  (let ((in  (open-input-file src))
        (out (open-output-file dst)))
    ;; Print the header of the C file
    (header in out)

    ;; Skip the two sexpr of the input file
    (read in)  ;; STklos string
    (read in)  ;; Information of the .ostk file

    ;; Print the constants vector one item per line (since git or emacs are
    ;; bad with long lines).
    ;; NOTE: There is a double write because we need to read back the values
    ;; and another one since the vector is stored in a C string.
    (let ((v   (read in)))
      (format out "char* STk_boot_consts = \"#(\"\n")
      (vector-for-each (lambda (x)
                         (write (with-output-to-string (lambda () (write x))) out)
                         (display " \" \"\n" out))
                       v)
      (format out "\")\";\n\n"))

    ;; Print the code vector
    (let ((sz (read in)))
      (format out "STk_instr STk_boot_code [] = { \n")
      (read-byte in)  ; To skip the newline after size
      (dotimes (i sz)
        (let* ((c1 (read-byte in))
               (c2 (read-byte in)))
          (format out
                  "0x~A"
                  (number->string (bit-or (bit-shift c1 8) c2) 16))
          (when (< i (- sz 1))
            (display ",\n" out))))
      (display "};\n" out))
    (flush-output-port out)
    (close-port out)))

;; ----------------------------------------------------------------------
;;      main ...
;; ----------------------------------------------------------------------
(define (main args)
  (if (= (length args) 3)
      (apply write-boot-file (cdr args))
      (die (format "Usage: ~A <boot image> <output>" (program-name)))))
