Commit 28c31342 authored by Thien-Thi Nguyen's avatar Thien-Thi Nguyen

New file

parent d72691f2
2001-04-29 Thien-Thi Nguyen <ttn@revel.glug.org>
* Makefile.am, PROGRAM, README, display-commentary,
doc-snarf, generate-autoload, punify, use2dot: New file
## Process this file with automake to produce Makefile.in.
##
## Copyright (C) 2001 Free Software Foundation, Inc.
##
## This file is part of GUILE.
##
## GUILE 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, or
## (at your option) any later version.
##
## GUILE 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 GUILE; see the file COPYING. If not, write
## to the Free Software Foundation, Inc., 59 Temple Place, Suite
## 330, Boston, MA 02111-1307 USA
AUTOMAKE_OPTIONS = foreign
# These should be installed and distributed.
scripts_sources = \
PROGRAM \
display-commentary \
doc-snarf \
generate-autoload \
punify \
use2dot
subpkgdatadir = $(pkgdatadir)/$(VERSION)/scripts
subpkgdata_SCRIPTS = $(scripts_sources)
EXTRA_DIST = $(scripts_sources)
overview:
@GUILE_LOAD_PATH=`(cd .. ; pwd)` \
./display-commentary $(scripts_sources)
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts PROGRAM)) '\'main')'
exec ${GUILE-guile} -c "(apply $main (cdr (command-line)))" "$@"
!#
;;; PROGRAM --- Does something
;; Copyright (C) 2001 Free Software Foundation, Inc.
;;
;; 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, 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 software; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA
;;; Commentary:
;; Usage: PROGRAM [ARGS]
;;
;; PROGRAM does something.
;;
;; TODO: Write it!
;;
;; Author: J.R.Hacker
;;; Code:
(define-module (scripts PROGRAM)
:export (PROGRAM))
(define (PROGRAM . args)
#t)
(define main PROGRAM)
;;; PROGRAM ends here
Overview and Usage
------------------
This directory contains Scheme programs, some useful in maintaining Guile.
On "make install", these programs are copied to PKGDATADIR/VERSION/scripts.
You can invoke a program from the shell, or alternatively, load its file
as a Guile Scheme module, and use its exported procedure(s) from Scheme code.
Typically for any PROGRAM:
(use-modules (scripts PROGRAM))
(PROGRAM ARG1 ARG2 ...)
For programs that write to stdout, you might try, instead:
(use-modules (scripts PROGRAM))
(with-output-to-string (lambda () (PROGRAM ARG1 ARG2 ...)))
Note that all args must be strings.
To see PROGRAM's commentary, which may or may not be helpful:
(help (scripts PROGRAM))
To see all commentaries and module dependencies, try: "make overview".
If you want to try the programs before installing Guile, you will probably
need to set environment variable GUILE_LOAD_PATH to be the parent directory.
This can be done in Bourne-compatible shells like so:
GUILE_LOAD_PATH=`(cd .. ; pwd)`
export GUILE_LOAD_PATH
[FIXME: Can someone supply the csh-compatible equivalent?]
How to Contribute
-----------------
See template file PROGRAM for a quick start.
Programs must follow the "executable module" convention, documented here:
- The file name must not end in ".scm".
- The file must be executable (chmod +x).
- The module name must be "(scripts PROGRAM)". A procedure named PROGRAM w/
signature "(PROGRAM . args)" must be exported. Basically, use some variant
of the form:
(define-module (scripts PROGRAM)
:export (PROGRAM))
Feel free to export other definitions useful in the module context.
- There must be the alias:
(define main PROGRAM)
However, `main' must NOT be exported.
- The beginning of the file must use the following invocation sequence:
#!/bin/sh
main='(module-ref (resolve-module '\''(scripts PROGRAM)) '\'main')'
exec ${GUILE-guile} -c "(apply $main (cdr (command-line)))" "$@"
!#
Following these conventions allows the program file to be used as module
(scripts PROGRAM) in addition to as a standalone executable. Please also
include a helpful Commentary section w/ some usage info.
[README ends here]
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts display-commentary)) '\'main')'
exec ${GUILE-guile} -c "(apply $main (cdr (command-line)))" "$@"
!#
;;; display-commentary --- As advertized
;; Copyright (C) 2001 Free Software Foundation, Inc.
;;
;; 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, 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 software; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA
;;; Commentary:
;; Usage: display-commentary FILE1 FILE2 ...
;;
;; Display Commentary section from FILE1, FILE2 and so on.
;;
;; Author: Thien-Thi Nguyen
;;; Code:
(define-module (scripts display-commentary)
:use-module (ice-9 documentation)
:export (display-commentary))
(define (display-commentary-one file)
(format #t "~A commentary:\n~A" file (file-commentary file)))
(define (display-commentary . files)
(for-each display-commentary-one files))
(define main display-commentary)
;;; display-commentary ends here
This diff is collapsed.
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts generate-autoload)) '\'main')'
exec ${GUILE-guile} -c "(apply $main (cdr (command-line)))" "$@"
!#
;;; generate-autoload --- Display define-module form with autoload info
;; Copyright (C) 2001 Free Software Foundation, Inc.
;;
;; 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, 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 software; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA
;;; Commentary:
;; Usage: generate-autoload [OPTIONS] FILE1 FILE2 ...
;;
;; The autoload form is displayed to standard output:
;;
;; (define-module (guile-user)
;; :autoload (ZAR FOO) (FOO-1 FOO-2 ...)
;; :
;; :
;; :autoload (ZAR BAR) (BAR-1 BAR-2 ...))
;;
;; For each file, a symbol triggers an autoload if it is found in one
;; of these situations:
;; - in the `:export' clause of a `define-module' form;
;; - in a top-level `export' or `export-syntax' form;
;; - in a `define-public' form.
;;
;; The module name is inferred from the `define-module' form. If either the
;; module name or the exports list cannot be determined, no autoload entry is
;; generated for that file.
;;
;; Options:
;; --target MODULE-NAME -- Use MODULE-NAME instead of `(guile-user)'.
;; Note that some shells may require you to
;; quote the argument to handle parentheses
;; and spaces.
;;
;; Usage examples from Scheme code as a module:
;; (use-modules (scripts generate-autoload))
;; (generate-autoload "generate-autoload")
;; (generate-autoload "--target" "(my module)" "generate-autoload")
;; (apply generate-autoload "--target" "(my module)" '("foo" "bar" "baz"))
;;
;; Author: Thien-Thi Nguyen
;;; Code:
(define-module (scripts generate-autoload)
:export (generate-autoload))
(define (autoload-info file)
(let ((p (open-input-file file)))
(let loop ((form (read p)) (module-name #f) (exports '()))
(if (eof-object? form)
(and module-name
(not (null? exports))
(list module-name exports)) ; ret
(cond ((and (list? form)
(< 1 (length form))
(eq? 'define-module (car form)))
(loop (read p)
(cadr form)
(cond ((member ':export form)
=> (lambda (val)
(append (cadr val) exports)))
(else exports))))
((and (list? form)
(< 1 (length form))
(memq (car form) '(export export-syntax)))
(loop (read p)
module-name
(append (cdr form) exports)))
((and (list? form)
(< 2 (length form))
(eq? 'define-public (car form))
(list? (cadr form))
(symbol? (caadr form)))
(loop (read p)
module-name
(cons (caadr form) exports)))
((and (list? form)
(< 2 (length form))
(eq? 'define-public (car form))
(symbol? (cadr form)))
(loop (read p)
module-name
(cons (cadr form) exports)))
(else (loop (read p) module-name exports)))))))
(define (generate-autoload . args)
(let* ((module-count 0)
(syms-count 0)
(target-override (cond ((member "--target" args) => cadr)
(else #f)))
(files (if target-override (cddr args) (cdr args))))
(display ";;; do not edit --- generated ")
(display (strftime "%Y-%m-%d %H:%M:%S" (localtime (current-time))))
(newline)
(display "(define-module ")
(display (or target-override "(guile-user)"))
(for-each (lambda (file)
(cond ((autoload-info file)
=> (lambda (info)
(and info
(apply (lambda (module-name exports)
(set! module-count (1+ module-count))
(set! syms-count (+ (length exports)
syms-count))
(for-each display
(list "\n :autoload "
module-name " "
exports)))
info))))))
files)
(display ")")
(newline)
(for-each display (list " ;;; "
syms-count " symbols in "
module-count " modules\n"))))
(define main generate-autoload)
;;; generate-autoload ends here
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts punify)) '\'main')'
exec ${GUILE-guile} -c "(apply $main (cdr (command-line)))" "$@"
!#
;;; punify --- Display Scheme code w/o unnecessary comments / whitespace
;; Copyright (C) 2001 Free Software Foundation, Inc.
;;
;; 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, 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 software; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA
;;; Commentary:
;; Usage: punify FILE1 FILE2 ...
;;
;; Each file's forms are read and written to stdout.
;; The effect is to remove comments and much non-essential whitespace.
;; This is useful when installing Scheme source to space-limited media.
;;
;; Example:
;; $ wc ./punify ; ./punify ./punify | wc
;; 81 355 2622 ./punify
;; 0 34 694
;;
;; TODO: Read from stdin.
;; Handle vectors.
;; Identifier punification.
;;
;; Author: Thien-Thi Nguyen
;;; Code:
(define-module (scripts punify)
:export (punify))
(define (write-punily form)
(if (and (list? form) (not (null? form)))
(let ((first (car form)))
(display "(")
(write-punily first)
(let loop ((ls (cdr form)) (last-was-list? (list? first)))
(if (null? ls)
(display ")")
(let* ((new-first (car ls))
(this-is-list? (list? new-first)))
(and (not last-was-list?)
(not this-is-list?)
(display " "))
(write-punily new-first)
(loop (cdr ls) this-is-list?)))))
(write form)))
(define (punify-one file)
(with-input-from-file file
(lambda ()
(let ((toke (lambda () (read (current-input-port)))))
(let loop ((form (toke)))
(or (eof-object? form)
(begin
(write-punily form)
(loop (toke)))))))))
(define (punify . args)
(for-each punify-one args))
(define main punify)
;;; punify ends here
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(scripts use2dot)) '\'main')'
exec ${GUILE-guile} -c "(apply $main (cdr (command-line)))" "$@"
!#
;;; use2dot --- Display module dependencies as a DOT specification
;; Copyright (C) 2001 Free Software Foundation, Inc.
;;
;; 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, 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 software; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
;; Boston, MA 02111-1307 USA
;;; Commentary:
;; Usage: use2dot [OPTIONS] [FILE ...]
;; Display to stdout a DOT specification that describes module dependencies
;; in FILEs.
;;
;; A top-level `use-modules' form or a `:use-module' `define-module'-component
;; results in a "solid" style edge.
;;
;; An `:autoload' `define-module'-component results in a "dotted" style edge
;; with label "N" indicating that N names are responsible for triggering the
;; autoload.
;;
;; A top-level `load' or `primitive-load' form results in a a "bold" style
;; edge to a node named with either the file name if the `load' argument is a
;; string, or "[computed in FILE]" otherwise.
;;
;; Options:
;; --default-module MOD -- Set MOD as the default module (for top-level
;; `use-modules' forms that do not follow some
;; `define-module' form in a file). MOD should be
;; be a list or `#f', in which case such top-level
;; `use-modules' forms are effectively ignored.
;; Default value: `(guile)'.
;;
;; TODO
;; - add `--load-synonyms' option
;; - add `--ignore-module' option
;; - handle arbitrary command-line key/value configuration
;;
;; Author: Thien-Thi Nguyen based on PERL script by Keisuke Nishida
;;; Code:
(define-module (scripts use2dot)
:use-module (ice-9 regex))
(define (string-append/separator separator strings)
;; from (ttn stringutils) -- todo: use srfi-13
;; "Append w/ SEPARATOR a list of STRINGS.
;; SEPARATOR can be a character or a string."
(let ((rev (reverse strings))
(sep (if (char? separator)
(make-string 1 separator)
separator)))
(apply string-append
(let loop ((s (cdr rev))
(acc (list (car rev))))
(if (null? s)
acc
(loop (cdr s)
(cons (car s)
(cons sep acc))))))))
(define (mapconcat proc ls sep)
;; from (ttn stringutils) -- todo: use srfi-13
;; "Map PROC over LS, concatening resulting strings with separator SEP."
(string-append/separator sep (map proc ls)))
(define default-module '(guile))
(define (q s) ; quote
(format #f "~S" s))
(define (vv pair) ; var=val
(format #f "~A=~A" (car pair) (cdr pair)))
(define (spew module use . etc)
(and module
(let ((etc-spec (if (null? etc)
""
(format #f " [~A]" (mapconcat vv etc ",")))))
(format #t " \"~A\" -> \"~A\"~A;\n" module use etc-spec))))
(define (header)
(format #t "digraph use2dot {")
(for-each (lambda (s) (format #t " ~A;\n" s))
(map vv `((label . ,(q "Guile Module Dependencies"))
;(rankdir . LR)
;(size . ,(q "7.5,10"))
(ratio . fill)
;(nodesep . ,(q "0.05"))
))))
(define (grok filename)
(let* ((p (open-file filename "r"))
(next (lambda () (read p)))
(curmod #f))
(let loop ((form (next)))
(cond ((eof-object? form))
((not (list? form)) (loop (next)))
(else (case (car form)
((define-module)
(let ((module (cadr form)))
(set! curmod module)
(let loop ((ls form))
(or (null? ls)
(case (car ls)
((:use-module)
(spew module (cadr ls))
(loop (cddr ls)))
((:autoload)
(spew module (cadr ls)
'(style . dotted)
'(fontsize . 5)
(let ((len (length (caddr ls))))
`(label . ,(q (number->string len)))))
(loop (cdddr ls)))
(else (loop (cdr ls))))))))
((use-modules)
(for-each (lambda (use)
(spew (or curmod default-module) use))
(cdr form)))
((load primitive-load)
(spew (or curmod default-module)
(let ((file (cadr form)))
(if (string? file)
file
(format #f "[computed in ~A]" filename)))
'(style . bold))))
(loop (next)))))))
(define (body files)
(for-each grok files))
(define (footer)
(format #t "}"))
(define (use2dot . args)
(header)
(let* ((override (cond ((member "--default-module" args) => cadr)
(else #f)))
(files (if override (cddr args) args)))
(and override
(set! default-module
(with-input-from-string override (lambda () (read)))))
(body files))
(footer))
(define main use2dot)
;;; use2dot ends here
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment