1 ;;;============================================================================
3 ;;; File: "main.scm", Time-stamp: <2009-08-03 13:04:49 feeley>
5 ;;; Copyright (c) 1994-2009 by Marc Feeley, All Rights Reserved.
7 ;;;----------------------------------------------------------------------------
9 (##define-macro (macro-initialization-file)
12 (define-prim (##main-gsi/gsc)
14 (define (in-homedir filename)
15 (let ((homedir (##path-expand "~")))
16 (##string-append homedir filename)))
18 (define (process-initialization-file)
20 (define (try filename)
23 (lambda (script-line script-path) #f)
28 (or (try (macro-initialization-file))
29 (try (in-homedir (macro-initialization-file)))))
31 (define (read-source-from-string str name)
33 (##open-input-string str)))
37 (lambda (port) name)))
39 (macro-character-port-input-readtable port))
41 (##read-all-as-a-begin-expr-from-port
46 (macro-readtable-start-syntax rt)
50 (define (interpreter-interactive-or-batch-mode arguments)
51 (let loop ((lst arguments)
59 (let ((option-name (convert-option file)))
60 (cond ((##string=? option-name "")
64 ((##string=? option-name "e")
66 (let ((src (read-source-from-string
69 (##eval-top src ##interaction-cte)
73 (warn-missing-argument-for-option "e")
77 (warn-unknown-option option-name)
83 (lambda (script-line script-path)
85 (let ((language-and-tail
86 (##extract-language-and-tail
90 (let ((language (##car language-and-tail)))
91 (##readtable-setup-for-language!
94 (##start-main language))
96 (set! ##processed-command-line
97 (##cons script-path rest)))))))
109 (if (##not batch-mode?)
113 (define (compiler-batch-mode options arguments)
115 (define (c-file? file)
116 (##string=? (##path-extension file) ".c"))
118 (define (obj-file? file)
119 (##string=? (##path-extension file) ##os-obj-extension-string-saved))
121 (let* ((opts (##map ##car options))
122 (sym-opts (##map ##string->symbol opts))
123 (c-opt? (##memq 'c sym-opts))
124 (link-opt? (##memq 'link sym-opts))
125 (exe-opt? (##memq 'exe sym-opts))
126 (obj-opt? (##memq 'obj sym-opts))
127 (dynamic-opt? (##memq 'dynamic sym-opts)))
128 (if (##fixnum.< 1 (##fixnum.+
133 (if dynamic-opt? 1 0)))
134 (warn-mutually-exclusive-options)
140 (else 'dyn)))) ;; dynamic is default
141 (let loop1 ((lst arguments)
145 (let ((file (##car lst))
147 (cond ((option? file)
148 (let ((option-name (convert-option file)))
149 (cond ((##string=? option-name "")
152 ((##string=? option-name "e")
153 (loop1 (if (##pair? rest)
158 (warn-unknown-option option-name)
163 (if (and (##eq? type 'obj)
164 (c#targ-generated-c-file? file))
165 (##fixnum.+ nb-output-files 1)
172 (##fixnum.+ nb-output-files 1)))))
175 (let ((x (##assoc "o" options)))
178 ((and (##not (##memq type '(link exe)))
179 (##fixnum.< 1 nb-output-files)
180 (let ((outdir (##path-normalize (##cdr x))))
183 (##path-strip-trailing-directory-separator
185 (warn-multiple-output-files-and-o-option)
190 (##assoc "prelude" options))
192 (##assoc "postlude" options))
194 (let ((x (##assoc "cc-options" options)))
199 (let ((x (##assoc "ld-options-prelude" options)))
204 (let ((x (##assoc "ld-options" options)))
215 (##source-locat program)))))
217 (##cons (##sourcify 'begin program)
221 (read-source-from-string
232 (read-source-from-string
242 (let ((rev-gen-c-files '())
246 (define (add-gen-c-file gen-c-file)
247 (set! rev-gen-c-files
251 (define (add-obj-file obj-file)
256 (define (add-tmp-file tmp-file)
264 (##reverse rev-tmp-files)))
266 (define (exit-abnormally)
270 (define (handling file)
271 (if (##fixnum.< 1 nb-output-files)
273 (lambda (first output-port)
274 (##write-string file output-port)
275 (##write-string ":\n" output-port)
278 (define (do-compile-file file sym-opts output)
285 cc-options: cc-options
286 ld-options-prelude: ld-options-prelude
287 ld-options: ld-options)
291 cc-options: cc-options
292 ld-options-prelude: ld-options-prelude
293 ld-options: ld-options))
296 (define (do-compile-file-to-c file sym-opts output)
308 (define (do-build-executable obj-files output-filename)
309 (or (##build-executable
318 (let loop2 ((lst arguments))
321 (let ((file (##car lst))
324 (let ((option-name (convert-option file)))
325 (cond ((##string=? option-name "")
328 ((##string=? option-name "e")
330 (let ((src (read-source-from-string
333 (##eval-top src ##interaction-cte)
334 (loop2 (##cdr rest)))
338 (let ((root (##path-strip-extension file)))
339 (cond ((c-file? file)
340 (if (##memq type '(exe obj))
344 (##cons 'obj sym-opts)
346 (##eq? type 'obj)))))
347 (add-obj-file obj-file)
348 (if (##eq? type 'exe)
349 (add-tmp-file obj-file))))
350 (if (and (##memq type '(link exe))
351 (c#targ-generated-c-file? file))
352 (add-gen-c-file file))
370 (##cons 'obj sym-opts)
372 (add-obj-file obj-file)))
375 (do-compile-file-to-c
380 (add-gen-c-file gen-c-file)
381 (if (##eq? type 'exe)
385 (##cons 'obj sym-opts)
387 (add-obj-file obj-file)
388 (add-tmp-file obj-file)
389 (add-tmp-file gen-c-file))))))
393 (##memq 'flat sym-opts))
395 (let ((x (##assoc "l" options)))
398 ((or (##not (##eq? type 'link))
400 (warn-no-incremental-link)
405 (if (##memq type '(link exe))
407 (if (##pair? rev-gen-c-files)
409 (##map ##path-strip-extension
410 (##reverse rev-gen-c-files)))
434 (add-gen-c-file link-file)
435 (if (##eq? type 'exe)
439 (##cons 'obj sym-opts)
441 (add-obj-file obj-link-file)
442 (add-tmp-file obj-link-file)
443 (if (##not (##memq 'keep-c options))
444 (add-tmp-file link-file))
446 (##reverse rev-obj-files))
450 (let ((expanded-output
452 (##path-normalize output))))
453 (if (and expanded-output
454 (##equal? expanded-output
455 (##path-strip-trailing-directory-separator
459 (##car (##reverse roots))
460 ##os-exe-extension-string-saved))))))
464 (warn-flat-and-not-link-or-exe)))
469 (define (warn-missing-argument-for-option opt)
471 (lambda (first output-port)
473 "*** WARNING -- Missing argument for option \""
475 (##write-string opt output-port)
476 (##write-string "\"\n" output-port)
479 (define (warn-unknown-option opt)
481 (lambda (first output-port)
483 "*** WARNING -- Unknown or improperly placed option: "
485 (##write opt output-port)
486 (##newline output-port)
489 (define (warn-multiple-output-files-and-o-option)
491 (lambda (first output-port)
493 "*** WARNING -- Multiple output files: non-directory \"o\" option ignored\n"
497 (define (warn-no-incremental-link)
499 (lambda (first output-port)
501 "*** WARNING -- No incremental link: \"l\" option ignored\n"
505 (define (warn-flat-and-not-link-or-exe)
507 (lambda (first output-port)
509 "*** WARNING -- \"link\" or \"exe\" options were not specified: \"flat\" option ignored\n"
513 (define (warn-mutually-exclusive-options)
515 (lambda (first output-port)
517 "*** WARNING -- The options \"c\", \"link\", \"dynamic\", \"exe\" and \"obj\" are mutually exclusive\n"
521 (define (option? arg)
522 (and (##fixnum.< 0 (##string-length arg))
523 (##char=? (##string-ref arg 0) #\-)))
525 (define (convert-option arg)
526 (##substring arg 1 (##string-length arg)))
528 (define (split-command-line
533 (let loop1 ((args arguments)
535 (if (and (##pair? args)
536 (option? (##car args)))
538 (let ((opt (convert-option (##car args)))
540 (cond ((##member opt options-with-no-args)
542 (##cons (##cons opt #f) rev-options)))
543 ((##member opt options-with-args)
546 (##cons (##cons opt (##car rest)) rev-options))
548 (warn-missing-argument-for-option opt)
549 (loop1 rest rev-options))))
551 (cont (##reverse rev-options) args))))
553 (cont (##reverse rev-options) args))))
555 (##load-support-libraries)
557 (let ((language-and-tail
558 (##extract-language-and-tail (##car ##processed-command-line))))
560 (if language-and-tail
561 (let ((language (##car language-and-tail)))
562 (##readtable-setup-for-language! (##current-readtable) language)))
565 (##cdr ##processed-command-line)
568 (lambda (main-options arguments)
569 (let ((skip-initialization-file?
570 (##assoc "f" main-options))
572 (or language-and-tail
573 (##assoc "i" main-options)))
575 (##assoc "v" main-options)))
578 (##write-string (##system-version-string) ##stdout-port)
579 (##write-string " " ##stdout-port)
580 (##write (##system-stamp) ##stdout-port)
581 (##write-string " " ##stdout-port)
582 (##write-string ##os-system-type-string-saved ##stdout-port)
583 (##write-string " " ##stdout-port)
584 (##write ##os-configure-command-string-saved ##stdout-port)
585 (##newline ##stdout-port)
589 (if (interpreter-or force-interpreter?)
591 '("c" "dynamic" "exe" "obj" "link" "flat"
592 "warnings" "verbose" "report" "expansion" "gvm"
593 "check" "force" "keep-c"
594 "debug" "debug-location" "debug-source" "debug-environments"
596 (if (interpreter-or force-interpreter?)
598 '("o" "l" "prelude" "postlude"
599 "cc-options" "ld-options-prelude" "ld-options"))
600 (lambda (known-options arguments)
602 (if (##not skip-initialization-file?)
603 (process-initialization-file))
605 (if (or (##null? arguments)
606 (interpreter-or force-interpreter?))
607 (interpreter-interactive-or-batch-mode arguments)
608 (compiler-batch-mode known-options arguments))))))))))
610 (##main-set! ##main-gsi/gsc)
612 (define-prim (main . args) ;; predefine main procedure so scripts don't have to
617 ;;;============================================================================