mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-02 13:00:26 +02:00
Still fixing screwups.
This commit is contained in:
parent
4304846e08
commit
8c81ca9fd2
10 changed files with 72 additions and 1115 deletions
2
scripts/.cvsignore
Normal file
2
scripts/.cvsignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
|
@ -1,134 +1,43 @@
|
||||||
2002-05-18 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* api-diff (group-diff): Also output +N and -N adds and subs
|
|
||||||
details, respectively.
|
|
||||||
|
|
||||||
2002-05-13 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* read-rfc822: New script.
|
|
||||||
|
|
||||||
* Makefile.am (scripts_sources): Add api-diff and read-rfc822.
|
|
||||||
|
|
||||||
* scan-api (scan-api): No longer include timestamp.
|
|
||||||
|
|
||||||
2002-05-11 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* scan-api (scan-api): Fix bug: No longer omit `C' and `Scheme' in
|
|
||||||
groups in the presence of the grouper.
|
|
||||||
|
|
||||||
* api-diff: Use modules (ice-9 format), (ice-9 getopt-long).
|
|
||||||
Autoload module (srfi srfi-13).
|
|
||||||
No longer export `diff-alists'.
|
|
||||||
|
|
||||||
(diff, diff-alists, display-list): Remove.
|
|
||||||
(put, get, read-api-alist-file, hang-by-the-roots, diff?,
|
|
||||||
diff+note!, group-diff): New procs.
|
|
||||||
(api-diff): Rewrite.
|
|
||||||
|
|
||||||
2002-05-10 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* scan-api (add-props): New proc.
|
|
||||||
(make-grok-proc): Renamed from `make-grok-hook'.
|
|
||||||
(make-members-proc): Renamed from `make-members-hook'.
|
|
||||||
(make-grouper): Renamed from `make-grouping-hook'. Update callers.
|
|
||||||
Add handling for multiple grouping-defs files.
|
|
||||||
(scan-api): Add handling for multiple grouping-defs files.
|
|
||||||
Cache `symbol->string' result; adjust `sort' usage.
|
|
||||||
|
|
||||||
2002-05-09 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* scan-api (scan-C!): Use more robust regexp.
|
|
||||||
|
|
||||||
2002-05-08 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* scan-api: New script.
|
|
||||||
(scan-api): Handle case where `grouping-hook' is #f.
|
|
||||||
|
|
||||||
Remove top-level `debug-enable' form.
|
|
||||||
Add TODO comment; nfc.
|
|
||||||
|
|
||||||
* Makefile.am (scripts_sources): Add "scan-api".
|
|
||||||
|
|
||||||
2002-04-30 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* summarize-guile-TODO (make-display-item):
|
|
||||||
Hoist some lambdas; nfc.
|
|
||||||
|
|
||||||
2002-04-29 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* summarize-guile-TODO: Fix commentary typo; nfc.
|
|
||||||
|
|
||||||
2002-04-08 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* summarize-guile-TODO: Use (ice-9 getopt-long).
|
|
||||||
Autoload (ice-9 common-list).
|
|
||||||
|
|
||||||
(select-items): New proc.
|
|
||||||
(make-display-item): New proc.
|
|
||||||
(display-item): Delete.
|
|
||||||
(display-items): Use `make-display-item'.
|
|
||||||
(summarize-guile-TODO): Add option handling.
|
|
||||||
|
|
||||||
2002-04-07 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* summarize-guile-TODO: Add "Bugs" section to commentary.
|
|
||||||
Autoload (srfi srfi-13) on `string-tokenize'.
|
|
||||||
|
|
||||||
(as-leaf): New proc.
|
|
||||||
(hang-by-the-leaves): Use `as-leaf'.
|
|
||||||
(read-TODO-file): Expand regexp and specs
|
|
||||||
to handle "D", "X" and "N%". Fix regexp
|
|
||||||
to make isolating `who' easier.
|
|
||||||
(display-item): Handle "D", "X" and "N%".
|
|
||||||
|
|
||||||
2002-04-06 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* summarize-guile-TODO: New script.
|
|
||||||
|
|
||||||
* Makefile.am (scripts_sources): Add "summarize-guile-TODO".
|
|
||||||
|
|
||||||
2002-04-05 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* read-text-outline (display-outline-tree): No longer export this proc.
|
|
||||||
|
|
||||||
(*depth-cue-rx*, *subm-number*, *level-divisor*, >>,
|
|
||||||
display-outline-tree): Delete these vars and procs.
|
|
||||||
|
|
||||||
(??, msub, ??-predicates, make-line-parser,
|
|
||||||
make-text-outline-reader): New procs.
|
|
||||||
|
|
||||||
(make-text-outline-reader): Export.
|
|
||||||
(read-text-outline-silently): Rewrite
|
|
||||||
using `make-text-outline-reader'.
|
|
||||||
|
|
||||||
2002-04-04 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
|
||||||
|
|
||||||
* lint: New script.
|
|
||||||
|
|
||||||
* Makefile.am (scripts_sources): Add "lint".
|
|
||||||
|
|
||||||
2002-04-02 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
2002-04-02 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
||||||
|
|
||||||
* PROGRAM: Update copyright; nfc.
|
* PROGRAM: Update copyright; nfc.
|
||||||
|
|
||||||
* read-text-outline: New script.
|
2002-03-24 Neil Jerram <neil@ossau.uklinux.net>
|
||||||
|
|
||||||
* Makefile.am (scripts_sources): Add "read-text-outline".
|
|
||||||
|
|
||||||
* read-text-outline (read-text-outline-silently):
|
|
||||||
Move `tp' inside `loop'; nfc.
|
|
||||||
|
|
||||||
2002-03-12 Neil Jerram <neil@ossau.uklinux.net>
|
|
||||||
|
|
||||||
* snarf-check-and-output-texi (snarf-check-and-output-texi): If
|
|
||||||
supplied, the `--manual' flag arrives as a string, not a symbol,
|
|
||||||
so test for it as such.
|
|
||||||
|
|
||||||
2002-03-03 Neil Jerram <neil@ossau.uklinux.net>
|
|
||||||
|
|
||||||
* snarf-guile-m4-docs (display-texi): Strip off `# ' from start of
|
* snarf-guile-m4-docs (display-texi): Strip off `# ' from start of
|
||||||
docstring lines if possible, rather than just `#'.
|
docstring lines if possible, rather than just `#'.
|
||||||
|
|
||||||
|
2002-03-14 Neil Jerram <neil@ossau.uklinux.net>
|
||||||
|
|
||||||
|
These changes add a @deffnx C function declaration and function
|
||||||
|
index entries for each Guile primitive to the copy of the doc
|
||||||
|
snarf output that is used for reference manual synchronization.
|
||||||
|
|
||||||
|
* snarf-check-and-output-texi (*manual-flag*,
|
||||||
|
snarf-check-and-output-texi): Handle `--manual' invocation arg
|
||||||
|
passed through from libguile/Makefile.am.
|
||||||
|
(*c-function-name*, begin-multiline, do-command): Pick out C
|
||||||
|
function name from snarfed token stream.
|
||||||
|
(end-multiline): Add @deffnx C declaration to output.
|
||||||
|
(*primitive-deffnx-signature*, *primitive-deffnx-sig-length*):
|
||||||
|
Fluff to help insert the C declaration after any "@deffnx
|
||||||
|
{Scheme Procedure}" lines in the snarfed docstring.
|
||||||
|
|
||||||
|
* snarf-check-and-output-texi: Change generated @deffn categories
|
||||||
|
from "primitive" to "Scheme Procedure".
|
||||||
|
|
||||||
|
2002-03-05 Neil Jerram <neil@ossau.uklinux.net>
|
||||||
|
|
||||||
|
* Makefile.am (scripts_sources): Add `lint'.
|
||||||
|
|
||||||
|
* lint: New script.
|
||||||
|
|
||||||
|
* frisk (grok-proc): Handle `#:xxx' as well as `:xxx'.
|
||||||
|
|
||||||
|
2002-03-04 Rob Browning <rlb@defaultvalue.org>
|
||||||
|
|
||||||
|
* Makefile.am (scripts_sources): add snarf-guile-m4-docs.
|
||||||
|
|
||||||
2002-02-26 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
2002-02-26 Thien-Thi Nguyen <ttn@giblet.glug.org>
|
||||||
|
|
||||||
* Makefile.am: Update path to pre-inst-guile automake frag.
|
* Makefile.am: Update path to pre-inst-guile automake frag.
|
||||||
|
@ -182,30 +91,6 @@
|
||||||
* use2dot (ferret): New proc.
|
* use2dot (ferret): New proc.
|
||||||
(grok): Use `ferret'.
|
(grok): Use `ferret'.
|
||||||
|
|
||||||
2001-11-16 Neil Jerram <neil@ossau.uklinux.net>
|
|
||||||
|
|
||||||
* snarf-check-and-output-texi: Change generated @deffn categories
|
|
||||||
from "function" and "primitive" to "C Function" and "Scheme
|
|
||||||
Procedure".
|
|
||||||
(end-multiline): Take out @findex generation again; not needed
|
|
||||||
since index entries are implicit in @deffn forms.
|
|
||||||
|
|
||||||
These changes add a @deffnx C function declaration and function
|
|
||||||
index entries for each Guile primitive to the copy of the doc
|
|
||||||
snarf output that is used for reference manual synchronization.
|
|
||||||
Online help is unchanged.
|
|
||||||
|
|
||||||
* snarf-check-and-output-texi (*manual-flag*,
|
|
||||||
snarf-check-and-output-texi): Handle `--manual' invocation arg
|
|
||||||
passed through from libguile/Makefile.am.
|
|
||||||
(*c-function-name*, begin-multiline, do-command): Pick out C
|
|
||||||
function name from snarfed token stream.
|
|
||||||
(end-multiline): Add @deffnx C declaration and function index
|
|
||||||
entries to output.
|
|
||||||
(*primitive-deffnx-signature*, *primitive-deffnx-sig-length*):
|
|
||||||
Fluff to help insert the C declaration after any "@deffnx
|
|
||||||
primitive" lines in the snarfed docstring.
|
|
||||||
|
|
||||||
2001-10-05 Thien-Thi Nguyen <ttn@glug.org>
|
2001-10-05 Thien-Thi Nguyen <ttn@glug.org>
|
||||||
|
|
||||||
* read-scheme-source (quoted?, clump): New procs, exported.
|
* read-scheme-source (quoted?, clump): New procs, exported.
|
||||||
|
@ -217,10 +102,6 @@
|
||||||
(display-commentary): Also handle refs that look like module
|
(display-commentary): Also handle refs that look like module
|
||||||
names.
|
names.
|
||||||
|
|
||||||
2001-08-25 Marius Vollmer <mvo@zagadka.ping.de>
|
|
||||||
|
|
||||||
* Makefile.am (AUTOMAKE_OPTIONS): Change "foreign" to "gnu".
|
|
||||||
|
|
||||||
2001-08-07 Michael Livshin <mlivshin@bigfoot.com>
|
2001-08-07 Michael Livshin <mlivshin@bigfoot.com>
|
||||||
|
|
||||||
* snarf-check-and-output-texi: print optional args in a prettier
|
* snarf-check-and-output-texi: print optional args in a prettier
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
## Process this file with automake to produce Makefile.in.
|
## Process this file with automake to produce Makefile.in.
|
||||||
##
|
##
|
||||||
## Copyright (C) 2002 Free Software Foundation, Inc.
|
## Copyright (C) 2001 Free Software Foundation, Inc.
|
||||||
##
|
##
|
||||||
## This file is part of GUILE.
|
## This file is part of GUILE.
|
||||||
##
|
##
|
||||||
|
@ -32,13 +32,9 @@ scripts_sources = \
|
||||||
lint \
|
lint \
|
||||||
punify \
|
punify \
|
||||||
read-scheme-source \
|
read-scheme-source \
|
||||||
read-text-outline \
|
|
||||||
use2dot \
|
use2dot \
|
||||||
snarf-check-and-output-texi \
|
snarf-check-and-output-texi \
|
||||||
summarize-guile-TODO \
|
snarf-guile-m4-docs
|
||||||
scan-api \
|
|
||||||
api-diff \
|
|
||||||
read-rfc822
|
|
||||||
|
|
||||||
subpkgdatadir = $(pkgdatadir)/$(VERSION)/scripts
|
subpkgdatadir = $(pkgdatadir)/$(VERSION)/scripts
|
||||||
subpkgdata_SCRIPTS = $(scripts_sources)
|
subpkgdata_SCRIPTS = $(scripts_sources)
|
||||||
|
|
161
scripts/api-diff
161
scripts/api-diff
|
@ -26,155 +26,60 @@ exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
||||||
;; Usage: api-diff [-d GROUPS] ALIST-FILE-A ALIST-FILE-B
|
;; Usage: api-diff alist-file-A alist-file-B
|
||||||
;;
|
|
||||||
;; Read in the alists from files ALIST-FILE-A and ALIST-FILE-B
|
;; Read in the alists from files ALIST-FILE-A and ALIST-FILE-B
|
||||||
;; and display a (count) summary of the groups defined therein.
|
;; and display four lists: old scheme, new scheme, old C, new C.
|
||||||
;; Optional arg "--details" (or "-d") specifies a comma-separated
|
|
||||||
;; list of groups, in which case api-diff displays instead the
|
|
||||||
;; elements added and deleted for each of the specified groups.
|
|
||||||
;;
|
;;
|
||||||
;; For scheme programming, this module exports the proc:
|
;; For scheme programming, the (scripts api-diff) module exports
|
||||||
|
;; two procedures:
|
||||||
|
;; (diff-alists A-alist B-alist report)
|
||||||
;; (api-diff A-file B-file)
|
;; (api-diff A-file B-file)
|
||||||
|
;; The latter implements the shell interface using the former.
|
||||||
|
;; REPORT is a proc that takes the above four lists. Its return
|
||||||
|
;; value is returned by `diff-alists'.
|
||||||
;;
|
;;
|
||||||
;; Note that the convention is that the "older" alist/file is
|
;; Note that the convention is that the "older" alist/file is
|
||||||
;; specified first.
|
;; specified first.
|
||||||
;;
|
;;
|
||||||
;; TODO: Develop scheme interface.
|
;; TODO: When the annotations support it, also detect/report
|
||||||
|
;; procedure signature, or other simple type, changes.
|
||||||
|
|
||||||
;;; Code:
|
;;; Code:
|
||||||
|
|
||||||
(define-module (scripts api-diff)
|
(define-module (scripts api-diff)
|
||||||
:use-module (ice-9 common-list)
|
:use-module (ice-9 common-list)
|
||||||
:use-module (ice-9 format)
|
:export (diff-alists api-diff))
|
||||||
:use-module (ice-9 getopt-long)
|
|
||||||
:autoload (srfi srfi-13) (string-tokenize)
|
|
||||||
:export (api-diff))
|
|
||||||
|
|
||||||
(define (read-alist-file file)
|
(define (read-alist-file file)
|
||||||
(with-input-from-file file
|
(with-input-from-file file
|
||||||
(lambda () (read))))
|
(lambda () (read))))
|
||||||
|
|
||||||
(define put set-object-property!)
|
(define (diff x y) (set-difference (map car x) (map car y)))
|
||||||
(define get object-property)
|
|
||||||
|
|
||||||
(define (read-api-alist-file file)
|
(define (diff-alists A B report)
|
||||||
(let* ((alist (read-alist-file file))
|
(let* ((A-scheme (assq-ref A 'scheme))
|
||||||
(meta (assq-ref alist 'meta))
|
(A-C (assq-ref A 'C))
|
||||||
(interface (assq-ref alist 'interface)))
|
(B-scheme (assq-ref B 'scheme))
|
||||||
(put interface 'meta meta)
|
(B-C (assq-ref B 'C))
|
||||||
(put interface 'groups (let ((ht (make-hash-table 31)))
|
(OLD-scheme (diff A-scheme B-scheme))
|
||||||
(for-each (lambda (group)
|
(NEW-scheme (diff B-scheme A-scheme))
|
||||||
(hashq-set! ht group '()))
|
(OLD-C (diff A-C B-C))
|
||||||
(assq-ref meta 'groups))
|
(NEW-C (diff B-C A-C)))
|
||||||
ht))
|
(report OLD-scheme NEW-scheme OLD-C NEW-C)))
|
||||||
interface))
|
|
||||||
|
|
||||||
(define (hang-by-the-roots interface)
|
(define (display-list head ls)
|
||||||
(let ((ht (get interface 'groups)))
|
(format #t ":: ~A -- ~A\n" head (length ls))
|
||||||
(for-each (lambda (x)
|
(for-each (lambda (x) (format #t "~A\n" x)) ls)
|
||||||
(for-each (lambda (group)
|
(newline))
|
||||||
(hashq-set! ht group
|
|
||||||
(cons (car x)
|
|
||||||
(hashq-ref ht group))))
|
|
||||||
(assq-ref x 'groups)))
|
|
||||||
interface))
|
|
||||||
interface)
|
|
||||||
|
|
||||||
(define (diff? a b)
|
|
||||||
(let ((result (set-difference a b)))
|
|
||||||
(if (null? result)
|
|
||||||
#f ; CL weenies bite me
|
|
||||||
result)))
|
|
||||||
|
|
||||||
(define (diff+note! a b note-removals note-additions note-same)
|
|
||||||
(let ((same? #t))
|
|
||||||
(cond ((diff? a b) => (lambda (x) (note-removals x) (set! same? #f))))
|
|
||||||
(cond ((diff? b a) => (lambda (x) (note-additions x) (set! same? #f))))
|
|
||||||
(and same? (note-same))))
|
|
||||||
|
|
||||||
(define (group-diff i-old i-new . options)
|
|
||||||
(let* ((i-old (hang-by-the-roots i-old))
|
|
||||||
(g-old (hash-fold acons '() (get i-old 'groups)))
|
|
||||||
(g-old-names (map car g-old))
|
|
||||||
(i-new (hang-by-the-roots i-new))
|
|
||||||
(g-new (hash-fold acons '() (get i-new 'groups)))
|
|
||||||
(g-new-names (map car g-new)))
|
|
||||||
(cond ((null? options)
|
|
||||||
(diff+note! g-old-names g-new-names
|
|
||||||
(lambda (removals)
|
|
||||||
(format #t "groups-removed: ~A\n" removals))
|
|
||||||
(lambda (additions)
|
|
||||||
(format #t "groups-added: ~A\n" additions))
|
|
||||||
(lambda () #t))
|
|
||||||
(for-each (lambda (group)
|
|
||||||
(let* ((old (assq-ref g-old group))
|
|
||||||
(new (assq-ref g-new group))
|
|
||||||
(old-count (and old (length old)))
|
|
||||||
(new-count (and new (length new)))
|
|
||||||
(delta (and old new (- new-count old-count))))
|
|
||||||
(format #t " ~5@A ~5@A : "
|
|
||||||
(or old-count "-")
|
|
||||||
(or new-count "-"))
|
|
||||||
(cond ((and old new)
|
|
||||||
(let ((add-count 0) (sub-count 0))
|
|
||||||
(diff+note!
|
|
||||||
old new
|
|
||||||
(lambda (subs)
|
|
||||||
(set! sub-count (length subs)))
|
|
||||||
(lambda (adds)
|
|
||||||
(set! add-count (length adds)))
|
|
||||||
(lambda () #t))
|
|
||||||
(format #t "~5@D ~5@D : ~5@D"
|
|
||||||
add-count (- sub-count) delta)))
|
|
||||||
(else
|
|
||||||
(format #t "~5@A ~5@A : ~5@A" "-" "-" "-")))
|
|
||||||
(format #t " ~A\n" group)))
|
|
||||||
(sort (union g-old-names g-new-names)
|
|
||||||
(lambda (a b)
|
|
||||||
(string<? (symbol->string a)
|
|
||||||
(symbol->string b))))))
|
|
||||||
((assq-ref options 'details)
|
|
||||||
=> (lambda (groups)
|
|
||||||
(for-each (lambda (group)
|
|
||||||
(let* ((old (or (assq-ref g-old group) '()))
|
|
||||||
(new (or (assq-ref g-new group) '()))
|
|
||||||
(>>! (lambda (label ls)
|
|
||||||
(format #t "~A ~A:\n" group label)
|
|
||||||
(for-each (lambda (x)
|
|
||||||
(format #t " ~A\n" x))
|
|
||||||
ls))))
|
|
||||||
(diff+note! old new
|
|
||||||
(lambda (removals)
|
|
||||||
(>>! 'removals removals))
|
|
||||||
(lambda (additions)
|
|
||||||
(>>! 'additions additions))
|
|
||||||
(lambda ()
|
|
||||||
(format #t "~A: no changes\n"
|
|
||||||
group)))))
|
|
||||||
groups)))
|
|
||||||
(else
|
|
||||||
(error "api-diff: group-diff: bad options")))))
|
|
||||||
|
|
||||||
(define (api-diff . args)
|
(define (api-diff . args)
|
||||||
(let* ((p (getopt-long (cons 'api-diff args)
|
(diff-alists (read-alist-file (list-ref args 0))
|
||||||
'((details (single-char #\d)
|
(read-alist-file (list-ref args 1))
|
||||||
(value #t))
|
(lambda (OLD-scheme NEW-scheme OLD-C NEW-C)
|
||||||
;; Add options here.
|
(display-list "OLD (deleted) scheme" OLD-scheme)
|
||||||
)))
|
(display-list "NEW scheme" NEW-scheme)
|
||||||
(rest (option-ref p '() '("/dev/null" "/dev/null")))
|
(display-list "OLD (deleted) C" OLD-C)
|
||||||
(i-old (read-api-alist-file (car rest)))
|
(display-list "NEW C" NEW-C))))
|
||||||
(i-new (read-api-alist-file (cadr rest)))
|
|
||||||
(options '()))
|
|
||||||
(cond ((option-ref p 'details #f)
|
|
||||||
=> (lambda (groups)
|
|
||||||
(set! options (cons (cons 'details
|
|
||||||
(map string->symbol
|
|
||||||
(string-tokenize
|
|
||||||
groups
|
|
||||||
#\,)))
|
|
||||||
options)))))
|
|
||||||
(apply group-diff i-old i-new options)))
|
|
||||||
|
|
||||||
(define main api-diff)
|
(define main api-diff)
|
||||||
|
|
||||||
|
|
|
@ -131,10 +131,10 @@ exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
||||||
(let loop ((ls form))
|
(let loop ((ls form))
|
||||||
(or (null? ls)
|
(or (null? ls)
|
||||||
(case (car ls)
|
(case (car ls)
|
||||||
((:use-module)
|
((:use-module #:use-module)
|
||||||
(note-use! 'regular module (ferret (cadr ls)))
|
(note-use! 'regular module (ferret (cadr ls)))
|
||||||
(loop (cddr ls)))
|
(loop (cddr ls)))
|
||||||
((:autoload)
|
((:autoload #:autoload)
|
||||||
(note-use! 'autoload module (cadr ls))
|
(note-use! 'autoload module (cadr ls))
|
||||||
(loop (cdddr ls)))
|
(loop (cdddr ls)))
|
||||||
(else (loop (cdr ls))))))))
|
(else (loop (cdr ls))))))))
|
||||||
|
|
|
@ -287,7 +287,7 @@ exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
||||||
(map (lambda (case)
|
(map (lambda (case)
|
||||||
(detect-free-variables (cdr case) locals))
|
(detect-free-variables (cdr case) locals))
|
||||||
(cddr x))))
|
(cddr x))))
|
||||||
|
|
||||||
((unquote unquote-splicing else =>)
|
((unquote unquote-splicing else =>)
|
||||||
(detect-free-variables-noncar (cdr x) locals))
|
(detect-free-variables-noncar (cdr x) locals))
|
||||||
|
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# aside from this initial boilerplate, this is actually -*- scheme -*- code
|
|
||||||
main='(module-ref (resolve-module '\''(scripts read-rfc822)) '\'main')'
|
|
||||||
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
|
||||||
!#
|
|
||||||
;;; read-rfc822 --- Validate RFC822 file by displaying it to stdout
|
|
||||||
|
|
||||||
;; Copyright (C) 2002 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
|
|
||||||
|
|
||||||
;;; Author: Thien-Thi Nguyen <ttn@gnu.org>
|
|
||||||
|
|
||||||
;;; Commentary:
|
|
||||||
|
|
||||||
;; Usage: read-rfc822 FILE
|
|
||||||
;;
|
|
||||||
;; Read FILE, assumed to be in RFC822 format, and display it to stdout.
|
|
||||||
;; This is not very interesting, admittedly.
|
|
||||||
;;
|
|
||||||
;; For Scheme programming, this module exports two procs:
|
|
||||||
;; (read-rfc822 . args) ; only first arg used
|
|
||||||
;; (read-rfc822-silently port)
|
|
||||||
;;
|
|
||||||
;; Parse FILE (a string) or PORT, respectively, and return a query proc that
|
|
||||||
;; takes a symbol COMP, and returns the message component COMP. Supported
|
|
||||||
;; values for COMP (and the associated query return values) are:
|
|
||||||
;; from -- #f (reserved for future mbox support)
|
|
||||||
;; headers -- alist of (HEADER-SYMBOL . "VALUE-STRING") pairs, in order
|
|
||||||
;; body -- rest of the mail message, a string
|
|
||||||
;; body-lines -- rest of the mail message, as a list of lines
|
|
||||||
;; Any other query results in a "bad component" error.
|
|
||||||
;;
|
|
||||||
;; TODO: Add "-m" option (mbox support).
|
|
||||||
|
|
||||||
;;; Code:
|
|
||||||
|
|
||||||
(define-module (scripts read-rfc822)
|
|
||||||
:use-module (ice-9 regex)
|
|
||||||
:use-module (ice-9 rdelim)
|
|
||||||
:autoload (srfi srfi-13) (string-join)
|
|
||||||
:export (read-rfc822 read-rfc822-silently))
|
|
||||||
|
|
||||||
(define from-line-rx (make-regexp "^From "))
|
|
||||||
(define header-name-rx (make-regexp "^([^:]+):[ \t]*"))
|
|
||||||
(define header-cont-rx (make-regexp "^[ \t]+"))
|
|
||||||
|
|
||||||
(define option #f) ; for future "-m"
|
|
||||||
|
|
||||||
(define (drain-message port)
|
|
||||||
(let loop ((line (read-line port)) (acc '()))
|
|
||||||
(cond ((eof-object? line)
|
|
||||||
(reverse acc))
|
|
||||||
((and option (regexp-exec from-line-rx line))
|
|
||||||
(for-each (lambda (c)
|
|
||||||
(unread-char c port))
|
|
||||||
(cons #\newline
|
|
||||||
(reverse (string->list line))))
|
|
||||||
(reverse acc))
|
|
||||||
(else
|
|
||||||
(loop (read-line port) (cons line acc))))))
|
|
||||||
|
|
||||||
(define (parse-message port)
|
|
||||||
(let* ((from (and option
|
|
||||||
(match:suffix (regexp-exec from-line-rx
|
|
||||||
(read-line port)))))
|
|
||||||
(body-lines #f)
|
|
||||||
(body #f)
|
|
||||||
(headers '())
|
|
||||||
(add-header! (lambda (reversed-hlines)
|
|
||||||
(let* ((hlines (reverse reversed-hlines))
|
|
||||||
(first (car hlines))
|
|
||||||
(m (regexp-exec header-name-rx first))
|
|
||||||
(name (string->symbol (match:substring m 1)))
|
|
||||||
(data (string-join
|
|
||||||
(cons (substring first (match:end m))
|
|
||||||
(cdr hlines))
|
|
||||||
" ")))
|
|
||||||
(set! headers (acons name data headers))))))
|
|
||||||
;; "From " is only one line
|
|
||||||
(let loop ((line (read-line port)) (current-header #f))
|
|
||||||
(cond ((string-null? line)
|
|
||||||
(and current-header (add-header! current-header))
|
|
||||||
(set! body-lines (drain-message port)))
|
|
||||||
((regexp-exec header-cont-rx line)
|
|
||||||
=> (lambda (m)
|
|
||||||
(loop (cdr lines)
|
|
||||||
(cons (match:suffix m) current-header))))
|
|
||||||
(else
|
|
||||||
(and current-header (add-header! current-header))
|
|
||||||
(loop (read-line port) (list line)))))
|
|
||||||
(set! headers (reverse headers))
|
|
||||||
(lambda (component)
|
|
||||||
(case component
|
|
||||||
((from) from)
|
|
||||||
((body-lines) body-lines)
|
|
||||||
((headers) headers)
|
|
||||||
((body) (or body
|
|
||||||
(begin (set! body (string-join body-lines "\n" 'suffix))
|
|
||||||
body)))
|
|
||||||
(else (error "bad component:" component))))))
|
|
||||||
|
|
||||||
(define (read-rfc822-silently port)
|
|
||||||
(parse-message port))
|
|
||||||
|
|
||||||
(define (display-rfc822 parse)
|
|
||||||
(cond ((parse 'from) => (lambda (from) (format #t "From ~A\n" from))))
|
|
||||||
(for-each (lambda (header)
|
|
||||||
(format #t "~A: ~A\n" (car header) (cdr header)))
|
|
||||||
(parse 'headers))
|
|
||||||
(format #t "\n~A" (parse 'body)))
|
|
||||||
|
|
||||||
(define (read-rfc822 . args)
|
|
||||||
(let ((parse (read-rfc822-silently (open-file (car args) OPEN_READ))))
|
|
||||||
(display-rfc822 parse))
|
|
||||||
#t)
|
|
||||||
|
|
||||||
(define main read-rfc822)
|
|
||||||
|
|
||||||
;;; read-rfc822 ends here
|
|
|
@ -1,255 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# aside from this initial boilerplate, this is actually -*- scheme -*- code
|
|
||||||
main='(module-ref (resolve-module '\''(scripts read-text-outline)) '\'main')'
|
|
||||||
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
|
||||||
!#
|
|
||||||
;;; read-text-outline --- Read a text outline and display it as a sexp
|
|
||||||
|
|
||||||
;; Copyright (C) 2002 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
|
|
||||||
|
|
||||||
;;; Author: Thien-Thi Nguyen <ttn@gnu.org>
|
|
||||||
|
|
||||||
;;; Commentary:
|
|
||||||
|
|
||||||
;; Usage: read-text-outline OUTLINE
|
|
||||||
;;
|
|
||||||
;; Scan OUTLINE file and display a list of trees, the structure of
|
|
||||||
;; each reflecting the "levels" in OUTLINE. The recognized outline
|
|
||||||
;; format (used to indicate outline headings) is zero or more pairs of
|
|
||||||
;; leading spaces followed by "-". Something like:
|
|
||||||
;;
|
|
||||||
;; - a 0
|
|
||||||
;; - b 1
|
|
||||||
;; - c 2
|
|
||||||
;; - d 1
|
|
||||||
;; - e 0
|
|
||||||
;; - f 1
|
|
||||||
;; - g 2
|
|
||||||
;; - h 1
|
|
||||||
;;
|
|
||||||
;; In this example the levels are shown to the right. The output for
|
|
||||||
;; such a file would be the single line:
|
|
||||||
;;
|
|
||||||
;; (("a" ("b" "c") "d") ("e" ("f" "g") "h"))
|
|
||||||
;;
|
|
||||||
;; Basically, anything at the beginning of a list is a parent, and the
|
|
||||||
;; remaining elements of that list are its children.
|
|
||||||
;;
|
|
||||||
;;
|
|
||||||
;; Usage from a Scheme program: These two procs are exported:
|
|
||||||
;;
|
|
||||||
;; (read-text-outline . args) ; only first arg is used
|
|
||||||
;; (read-text-outline-silently port)
|
|
||||||
;; (make-text-outline-reader re specs)
|
|
||||||
;;
|
|
||||||
;; `make-text-outline-reader' returns a proc that reads from PORT and
|
|
||||||
;; returns a list of trees (similar to `read-text-outline-silently').
|
|
||||||
;;
|
|
||||||
;; RE is a regular expression (string) that is used to identify a header
|
|
||||||
;; line of the outline (as opposed to a whitespace line or intervening
|
|
||||||
;; text). RE must begin w/ a sub-expression to match the "level prefix"
|
|
||||||
;; of the line. You can use `level-submatch-number' in SPECS (explained
|
|
||||||
;; below) to specify a number other than 1, the default.
|
|
||||||
;;
|
|
||||||
;; Normally, the level of the line is taken directly as the length of
|
|
||||||
;; its level prefix. This often results in adjacent levels not mapping
|
|
||||||
;; to adjacent numbers, which confuses the tree-building portion of the
|
|
||||||
;; program, which expects top-level to be 0, first sub-level to be 1,
|
|
||||||
;; etc. You can use `level-substring-divisor' or `compute-level' in
|
|
||||||
;; SPECS to specify a constant scaling factor or specify a completely
|
|
||||||
;; alternative procedure, respectively.
|
|
||||||
;;
|
|
||||||
;; SPECS is an alist which may contain the following key/value pairs:
|
|
||||||
;;
|
|
||||||
;; - level-submatch-number NUMBER
|
|
||||||
;; - level-substring-divisor NUMBER
|
|
||||||
;; - compute-level PROC
|
|
||||||
;; - body-submatch-number NUMBER
|
|
||||||
;; - extra-fields ((FIELD-1 . SUBMATCH-1) (FIELD-2 . SUBMATCH-2) ...)
|
|
||||||
;;
|
|
||||||
;; The PROC value associated with key `compute-level' should take a
|
|
||||||
;; Scheme match structure (as returned by `regexp-exec') and return a
|
|
||||||
;; number, the normalized level for that line. If this is specified,
|
|
||||||
;; it takes precedence over other level-computation methods.
|
|
||||||
;;
|
|
||||||
;; Use `body-submatch-number' if RE specifies the whole body, or if you
|
|
||||||
;; want to make use of the extra fields parsing. The `extra-fields'
|
|
||||||
;; value is a sub-alist, whose keys name additional fields that are to
|
|
||||||
;; be recognized. These fields along with `level' are set as object
|
|
||||||
;; properties of the final string ("body") that is consed into the tree.
|
|
||||||
;; If a field name ends in "?" the field value is set to be #t if there
|
|
||||||
;; is a match and the result is not an empty string, and #f otherwise.
|
|
||||||
;;
|
|
||||||
;;
|
|
||||||
;; Bugs and caveats:
|
|
||||||
;;
|
|
||||||
;; (1) Only the first file specified on the command line is scanned.
|
|
||||||
;; (2) TAB characters at the beginnings of lines are not recognized.
|
|
||||||
;; (3) Outlines that "skip" levels signal an error. In other words,
|
|
||||||
;; this will fail:
|
|
||||||
;;
|
|
||||||
;; - a 0
|
|
||||||
;; - b 1
|
|
||||||
;; - c 3 <-- skipped 2 -- error!
|
|
||||||
;; - d 1
|
|
||||||
;;
|
|
||||||
;;
|
|
||||||
;; TODO: Determine what's the right thing to do for skips.
|
|
||||||
;; Handle TABs.
|
|
||||||
;; Make line format customizable via longopts.
|
|
||||||
|
|
||||||
;;; Code:
|
|
||||||
|
|
||||||
(define-module (scripts read-text-outline)
|
|
||||||
:export (read-text-outline
|
|
||||||
read-text-outline-silently
|
|
||||||
make-text-outline-reader)
|
|
||||||
:use-module (ice-9 regex)
|
|
||||||
:autoload (ice-9 rdelim) (read-line)
|
|
||||||
:autoload (ice-9 getopt-long) (getopt-long))
|
|
||||||
|
|
||||||
(define (?? symbol)
|
|
||||||
(let ((name (symbol->string symbol)))
|
|
||||||
(string=? "?" (substring name (1- (string-length name))))))
|
|
||||||
|
|
||||||
(define (msub n)
|
|
||||||
(lambda (m)
|
|
||||||
(match:substring m n)))
|
|
||||||
|
|
||||||
(define (??-predicates pair)
|
|
||||||
(cons (car pair)
|
|
||||||
(if (?? (car pair))
|
|
||||||
(lambda (m)
|
|
||||||
(not (string=? "" (match:substring m (cdr pair)))))
|
|
||||||
(msub (cdr pair)))))
|
|
||||||
|
|
||||||
(define (make-line-parser re specs)
|
|
||||||
(let* ((rx (let ((fc (substring re 0 1)))
|
|
||||||
(make-regexp (if (string=? "^" fc)
|
|
||||||
re
|
|
||||||
(string-append "^" re)))))
|
|
||||||
(check (lambda (key)
|
|
||||||
(assq-ref specs key)))
|
|
||||||
(level-substring (msub (or (check 'level-submatch-number) 1)))
|
|
||||||
(extract-level (cond ((check 'compute-level)
|
|
||||||
=> (lambda (proc)
|
|
||||||
(lambda (m)
|
|
||||||
(proc m))))
|
|
||||||
((check 'level-substring-divisor)
|
|
||||||
=> (lambda (n)
|
|
||||||
(lambda (m)
|
|
||||||
(/ (string-length (level-substring m))
|
|
||||||
n))))
|
|
||||||
(else
|
|
||||||
(lambda (m)
|
|
||||||
(string-length (level-substring m))))))
|
|
||||||
(extract-body (cond ((check 'body-submatch-number)
|
|
||||||
=> msub)
|
|
||||||
(else
|
|
||||||
(lambda (m) (match:suffix m)))))
|
|
||||||
(misc-props! (cond ((check 'extra-fields)
|
|
||||||
=> (lambda (alist)
|
|
||||||
(let ((new (map ??-predicates alist)))
|
|
||||||
(lambda (obj m)
|
|
||||||
(for-each
|
|
||||||
(lambda (pair)
|
|
||||||
(set-object-property!
|
|
||||||
obj (car pair)
|
|
||||||
((cdr pair) m)))
|
|
||||||
new)))))
|
|
||||||
(else
|
|
||||||
(lambda (obj m) #t)))))
|
|
||||||
;; retval
|
|
||||||
(lambda (line)
|
|
||||||
(cond ((regexp-exec rx line)
|
|
||||||
=> (lambda (m)
|
|
||||||
(let ((level (extract-level m))
|
|
||||||
(body (extract-body m)))
|
|
||||||
(set-object-property! body 'level level)
|
|
||||||
(misc-props! body m)
|
|
||||||
body)))
|
|
||||||
(else #f)))))
|
|
||||||
|
|
||||||
(define (make-text-outline-reader re specs)
|
|
||||||
(let ((parse-line (make-line-parser re specs)))
|
|
||||||
;; retval
|
|
||||||
(lambda (port)
|
|
||||||
(let* ((all '(start))
|
|
||||||
(pchain (list))) ; parents chain
|
|
||||||
(let loop ((line (read-line port))
|
|
||||||
(prev-level -1) ; how this relates to the first input
|
|
||||||
; level determines whether or not we
|
|
||||||
; start in "sibling" or "child" mode.
|
|
||||||
; in the end, `start' is ignored and
|
|
||||||
; it's much easier to ignore parents
|
|
||||||
; than siblings (sometimes). this is
|
|
||||||
; not to encourage ignorance, however.
|
|
||||||
(tp all)) ; tail pointer
|
|
||||||
(or (eof-object? line)
|
|
||||||
(cond ((parse-line line)
|
|
||||||
=> (lambda (w)
|
|
||||||
(let* ((words (list w))
|
|
||||||
(level (object-property w 'level))
|
|
||||||
(diff (- level prev-level)))
|
|
||||||
(cond
|
|
||||||
|
|
||||||
;; sibling
|
|
||||||
((zero? diff)
|
|
||||||
;; just extend the chain
|
|
||||||
(set-cdr! tp words))
|
|
||||||
|
|
||||||
;; child
|
|
||||||
((positive? diff)
|
|
||||||
(or (= 1 diff)
|
|
||||||
(error "unhandled diff not 1:" diff line))
|
|
||||||
;; parent may be contacted by uncle later (kids
|
|
||||||
;; these days!) so save its level
|
|
||||||
(set-object-property! tp 'level prev-level)
|
|
||||||
(set! pchain (cons tp pchain))
|
|
||||||
;; "push down" car into hierarchy
|
|
||||||
(set-car! tp (cons (car tp) words)))
|
|
||||||
|
|
||||||
;; uncle
|
|
||||||
((negative? diff)
|
|
||||||
;; prune back to where levels match
|
|
||||||
(do ((p pchain (cdr p)))
|
|
||||||
((= level (object-property (car p) 'level))
|
|
||||||
(set! pchain p)))
|
|
||||||
;; resume at this level
|
|
||||||
(set-cdr! (car pchain) words)
|
|
||||||
(set! pchain (cdr pchain))))
|
|
||||||
|
|
||||||
(loop (read-line port) level words))))
|
|
||||||
(else (loop (read-line port) prev-level tp)))))
|
|
||||||
(set! all (car all))
|
|
||||||
(if (eq? 'start all)
|
|
||||||
'() ; wasteland
|
|
||||||
(cdr all))))))
|
|
||||||
|
|
||||||
(define read-text-outline-silently
|
|
||||||
(make-text-outline-reader "(([ ][ ])*)- *"
|
|
||||||
'((level-substring-divisor . 2))))
|
|
||||||
|
|
||||||
(define (read-text-outline . args)
|
|
||||||
(write (read-text-outline-silently (open-file (car args) "r")))
|
|
||||||
(newline)
|
|
||||||
#t) ; exit val
|
|
||||||
|
|
||||||
(define main read-text-outline)
|
|
||||||
|
|
||||||
;;; read-text-outline ends here
|
|
225
scripts/scan-api
225
scripts/scan-api
|
@ -1,225 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# aside from this initial boilerplate, this is actually -*- scheme -*- code
|
|
||||||
main='(module-ref (resolve-module '\''(scripts scan-api)) '\'main')'
|
|
||||||
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
|
||||||
!#
|
|
||||||
;;; scan-api --- Scan and group interpreter and libguile interface elements
|
|
||||||
|
|
||||||
;; Copyright (C) 2002 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
|
|
||||||
|
|
||||||
;;; Author: Thien-Thi Nguyen <ttn@gnu.org>
|
|
||||||
|
|
||||||
;;; Commentary:
|
|
||||||
|
|
||||||
;; Usage: scan-api GUILE SOFILE [GROUPINGS ...]
|
|
||||||
;;
|
|
||||||
;; Invoke GUILE, an executable guile interpreter, and use nm(1) on SOFILE, a
|
|
||||||
;; shared-object library, to determine available interface elements, and
|
|
||||||
;; display them to stdout as an alist:
|
|
||||||
;;
|
|
||||||
;; ((meta ...) (interface ...))
|
|
||||||
;;
|
|
||||||
;; The meta fields are `GUILE_LOAD_PATH', `LTDL_LIBRARY_PATH', `guile'
|
|
||||||
;; `libguileinterface', `sofile' and `groups'. The interface elements are in
|
|
||||||
;; turn sub-alists w/ keys `groups' and `scan-data'. Interface elements
|
|
||||||
;; initially belong in one of two groups `Scheme' or `C' (but not both --
|
|
||||||
;; signal error if that happens).
|
|
||||||
;;
|
|
||||||
;; Optional GROUPINGS ... are files each containing a single "grouping
|
|
||||||
;; definition" alist with each entry of the form:
|
|
||||||
;;
|
|
||||||
;; (NAME (description "DESCRIPTION") (members SYM...))
|
|
||||||
;;
|
|
||||||
;; All of the SYM... should be proper subsets of the interface. In addition
|
|
||||||
;; to `description' and `members' forms, the entry may optionally include:
|
|
||||||
;;
|
|
||||||
;; (grok USE-MODULES (lambda (x) CODE))
|
|
||||||
;;
|
|
||||||
;; where CODE implements a group-membership predicate to be applied to `x', a
|
|
||||||
;; symbol. [When evaluated, CODE can assume (use-modules MODULE) has been
|
|
||||||
;; executed where MODULE is an element of USE-MODULES, a list. [NOT YET
|
|
||||||
;; IMPLEMENTED!]]
|
|
||||||
;;
|
|
||||||
;; Currently, there are two convenience predicates that operate on `x':
|
|
||||||
;; (in-group? x GROUP)
|
|
||||||
;; (name-prefix? x PREFIX)
|
|
||||||
;;
|
|
||||||
;; TODO: Allow for concurrent Scheme/C membership.
|
|
||||||
;; Completely separate reporting.
|
|
||||||
|
|
||||||
;;; Code:
|
|
||||||
|
|
||||||
(define-module (scripts scan-api)
|
|
||||||
:use-module (ice-9 popen)
|
|
||||||
:use-module (ice-9 rdelim)
|
|
||||||
:use-module (ice-9 regex)
|
|
||||||
:export (scan-api))
|
|
||||||
|
|
||||||
(define put set-object-property!)
|
|
||||||
(define get object-property)
|
|
||||||
|
|
||||||
(define (add-props object . args)
|
|
||||||
(let loop ((args args))
|
|
||||||
(if (null? args)
|
|
||||||
object ; retval
|
|
||||||
(let ((key (car args))
|
|
||||||
(value (cadr args)))
|
|
||||||
(put object key value)
|
|
||||||
(loop (cddr args))))))
|
|
||||||
|
|
||||||
(define (scan re command match)
|
|
||||||
(let ((rx (make-regexp re))
|
|
||||||
(port (open-pipe command OPEN_READ)))
|
|
||||||
(let loop ((line (read-line port)))
|
|
||||||
(or (eof-object? line)
|
|
||||||
(begin
|
|
||||||
(cond ((regexp-exec rx line) => match))
|
|
||||||
(loop (read-line port)))))))
|
|
||||||
|
|
||||||
(define (scan-Scheme! ht guile)
|
|
||||||
(scan "^.guile.+: ([^ \t]+)([ \t]+(.+))*$"
|
|
||||||
(format #f "~A -c '~S ~S'"
|
|
||||||
guile
|
|
||||||
'(use-modules (ice-9 session))
|
|
||||||
'(apropos "."))
|
|
||||||
(lambda (m)
|
|
||||||
(let ((x (string->symbol (match:substring m 1))))
|
|
||||||
(put x 'Scheme (or (match:substring m 3)
|
|
||||||
""))
|
|
||||||
(hashq-set! ht x #t)))))
|
|
||||||
|
|
||||||
(define (scan-C! ht sofile)
|
|
||||||
(scan "^[0-9a-fA-F]+ ([B-TV-Z]) (.+)$"
|
|
||||||
(format #f "nm ~A" sofile)
|
|
||||||
(lambda (m)
|
|
||||||
(let ((x (string->symbol (match:substring m 2))))
|
|
||||||
(put x 'C (string->symbol (match:substring m 1)))
|
|
||||||
(and (hashq-get-handle ht x)
|
|
||||||
(error "both Scheme and C:" x))
|
|
||||||
(hashq-set! ht x #t)))))
|
|
||||||
|
|
||||||
(define THIS-MODULE (current-module))
|
|
||||||
|
|
||||||
(define (in-group? x group)
|
|
||||||
(memq group (get x 'groups)))
|
|
||||||
|
|
||||||
(define (name-prefix? x prefix)
|
|
||||||
(string-match (string-append "^" prefix) (symbol->string x)))
|
|
||||||
|
|
||||||
(define (add-group-name! x name)
|
|
||||||
(put x 'groups (cons name (get x 'groups))))
|
|
||||||
|
|
||||||
(define (make-grok-proc name form)
|
|
||||||
(let* ((predicate? (eval form THIS-MODULE))
|
|
||||||
(p (lambda (x)
|
|
||||||
(and (predicate? x)
|
|
||||||
(add-group-name! x name)))))
|
|
||||||
(put p 'name name)
|
|
||||||
p))
|
|
||||||
|
|
||||||
(define (make-members-proc name members)
|
|
||||||
(let ((p (lambda (x)
|
|
||||||
(and (memq x members)
|
|
||||||
(add-group-name! x name)))))
|
|
||||||
(put p 'name name)
|
|
||||||
p))
|
|
||||||
|
|
||||||
(define (make-grouper files) ; \/^^^o/ . o
|
|
||||||
(let ((hook (make-hook 1))) ; /\____\
|
|
||||||
(for-each
|
|
||||||
(lambda (file)
|
|
||||||
(for-each
|
|
||||||
(lambda (gdef)
|
|
||||||
(let ((name (car gdef))
|
|
||||||
(members (assq-ref gdef 'members))
|
|
||||||
(grok (assq-ref gdef 'grok)))
|
|
||||||
(or members grok
|
|
||||||
(error "bad grouping, must have `members' or `grok'"))
|
|
||||||
(add-hook! hook
|
|
||||||
(if grok
|
|
||||||
(add-props (make-grok-proc name (cadr grok))
|
|
||||||
'description
|
|
||||||
(assq-ref gdef 'description))
|
|
||||||
(make-members-proc name members))
|
|
||||||
#t))) ; append
|
|
||||||
(read (open-file file OPEN_READ))))
|
|
||||||
files)
|
|
||||||
hook))
|
|
||||||
|
|
||||||
(define (scan-api . args)
|
|
||||||
(let ((guile (list-ref args 0))
|
|
||||||
(sofile (list-ref args 1))
|
|
||||||
(grouper (false-if-exception (make-grouper (cddr args))))
|
|
||||||
(ht (make-hash-table 3331)))
|
|
||||||
(scan-Scheme! ht guile)
|
|
||||||
(scan-C! ht sofile)
|
|
||||||
(let ((all (sort (hash-fold (lambda (key value prior-result)
|
|
||||||
(add-props
|
|
||||||
key
|
|
||||||
'string (symbol->string key)
|
|
||||||
'scan-data (or (get key 'Scheme)
|
|
||||||
(get key 'C))
|
|
||||||
'groups (if (get key 'Scheme)
|
|
||||||
'(Scheme)
|
|
||||||
'(C)))
|
|
||||||
(and grouper (run-hook grouper key))
|
|
||||||
(cons key prior-result))
|
|
||||||
'()
|
|
||||||
ht)
|
|
||||||
(lambda (a b)
|
|
||||||
(string<? (get a 'string)
|
|
||||||
(get b 'string))))))
|
|
||||||
(format #t ";;; generated by scan-api -- do not edit!\n\n")
|
|
||||||
(format #t "(\n")
|
|
||||||
(format #t "(meta\n")
|
|
||||||
(format #t " (GUILE_LOAD_PATH . ~S)\n"
|
|
||||||
(or (getenv "GUILE_LOAD_PATH") ""))
|
|
||||||
(format #t " (LTDL_LIBRARY_PATH . ~S)\n"
|
|
||||||
(or (getenv "LTDL_LIBRARY_PATH") ""))
|
|
||||||
(format #t " (guile . ~S)\n" guile)
|
|
||||||
(format #t " (libguileinterface . ~S)\n"
|
|
||||||
(let ((i #f))
|
|
||||||
(scan "(.+)"
|
|
||||||
(format #f "~A -c '(display ~A)'"
|
|
||||||
guile
|
|
||||||
'(assq-ref %guile-build-info
|
|
||||||
'libguileinterface))
|
|
||||||
(lambda (m) (set! i (match:substring m 1))))
|
|
||||||
i))
|
|
||||||
(format #t " (sofile . ~S)\n" sofile)
|
|
||||||
(format #t " ~A\n"
|
|
||||||
(cons 'groups (append (if grouper
|
|
||||||
(map (lambda (p) (get p 'name))
|
|
||||||
(hook->list grouper))
|
|
||||||
'())
|
|
||||||
'(Scheme C))))
|
|
||||||
(format #t ") ;; end of meta\n")
|
|
||||||
(format #t "(interface\n")
|
|
||||||
(for-each (lambda (x)
|
|
||||||
(format #t "(~A ~A (scan-data ~S))\n"
|
|
||||||
x
|
|
||||||
(cons 'groups (get x 'groups))
|
|
||||||
(get x 'scan-data)))
|
|
||||||
all)
|
|
||||||
(format #t ") ;; end of interface\n")
|
|
||||||
(format #t ") ;; eof\n")))
|
|
||||||
#t)
|
|
||||||
|
|
||||||
(define main scan-api)
|
|
||||||
|
|
||||||
;;; scan-api ends here
|
|
|
@ -1,214 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# aside from this initial boilerplate, this is actually -*- scheme -*- code
|
|
||||||
main='(module-ref (resolve-module '\''(scripts summarize-guile-TODO)) '\'main')'
|
|
||||||
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
|
|
||||||
!#
|
|
||||||
;;; summarize-guile-TODO --- Display Guile TODO list in various ways
|
|
||||||
|
|
||||||
;; Copyright (C) 2002 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
|
|
||||||
|
|
||||||
;;; Author: Thien-Thi Nguyen <ttn@gnu.org>
|
|
||||||
|
|
||||||
;;; Commentary:
|
|
||||||
|
|
||||||
;; Usage: summarize-guile-TODO TODOFILE
|
|
||||||
;;
|
|
||||||
;; The TODOFILE is typically Guile's (see workbook/tasks/README)
|
|
||||||
;; presumed to serve as our signal to ourselves (lest we want real
|
|
||||||
;; bosses hassling us) wrt to the overt message "items to do" as well as
|
|
||||||
;; the messages that can be inferred from its structure.
|
|
||||||
;;
|
|
||||||
;; This program reads TODOFILE and displays interpretations on its
|
|
||||||
;; structure, including registered markers and ownership, in various
|
|
||||||
;; ways.
|
|
||||||
;;
|
|
||||||
;; A primary interest in any task is its parent task. The output
|
|
||||||
;; summarization by default lists every item and its parent chain.
|
|
||||||
;; Top-level parents are not items. You can use these command-line
|
|
||||||
;; options to modify the selection and display (selection criteria
|
|
||||||
;; are ANDed together):
|
|
||||||
;;
|
|
||||||
;; -i, --involved USER -- select USER-involved items
|
|
||||||
;; -p, --personal USER -- select USER-responsible items
|
|
||||||
;; -t, --todo -- select unfinished items (status "-")
|
|
||||||
;; -d, --done -- select finished items (status "+")
|
|
||||||
;; -r, --review -- select review items (marker "R")
|
|
||||||
;;
|
|
||||||
;; -w, --who -- also show who is associated w/ the item
|
|
||||||
;; -n, --no-parent -- do not show parent chain
|
|
||||||
;;
|
|
||||||
;;
|
|
||||||
;; Usage from a Scheme program:
|
|
||||||
;; (summarize-guile-TODO . args) ; uses first arg only
|
|
||||||
;;
|
|
||||||
;;
|
|
||||||
;; Bugs: (1) Markers are scanned in sequence: D R X N%. This means "XD"
|
|
||||||
;; and the like are completely dropped. However, such strings
|
|
||||||
;; are unlikely to be used if the markers are chosen to be
|
|
||||||
;; somewhat exclusive, which is currently the case for D R X.
|
|
||||||
;; N% used w/ these needs to be something like: "D25%" (this
|
|
||||||
;; means discussion accounts for 1/4 of the task).
|
|
||||||
;;
|
|
||||||
;; TODO: Implement more various ways. (Patches welcome.)
|
|
||||||
;; Add support for ORing criteria.
|
|
||||||
|
|
||||||
;;; Code:
|
|
||||||
(debug-enable 'debug 'backtrace)
|
|
||||||
|
|
||||||
(define-module (scripts summarize-guile-TODO)
|
|
||||||
:use-module (scripts read-text-outline)
|
|
||||||
:use-module (ice-9 getopt-long)
|
|
||||||
:autoload (srfi srfi-13) (string-tokenize) ; string library
|
|
||||||
:autoload (ice-9 common-list) (remove-if-not)
|
|
||||||
:export (summarize-guile-TODO))
|
|
||||||
|
|
||||||
(define put set-object-property!)
|
|
||||||
(define get object-property)
|
|
||||||
|
|
||||||
(define (as-leaf x)
|
|
||||||
(cond ((get x 'who)
|
|
||||||
=> (lambda (who)
|
|
||||||
(put x 'who
|
|
||||||
(map string->symbol
|
|
||||||
(string-tokenize who #\:))))))
|
|
||||||
(cond ((get x 'pct-done)
|
|
||||||
=> (lambda (pct-done)
|
|
||||||
(put x 'pct-done (string->number pct-done)))))
|
|
||||||
x)
|
|
||||||
|
|
||||||
(define (hang-by-the-leaves trees)
|
|
||||||
(let ((leaves '()))
|
|
||||||
(letrec ((hang (lambda (tree parent)
|
|
||||||
(if (list? tree)
|
|
||||||
(begin
|
|
||||||
(put (car tree) 'parent parent)
|
|
||||||
(for-each (lambda (child)
|
|
||||||
(hang child (car tree)))
|
|
||||||
(cdr tree)))
|
|
||||||
(begin
|
|
||||||
(put tree 'parent parent)
|
|
||||||
(set! leaves (cons (as-leaf tree) leaves)))))))
|
|
||||||
(for-each (lambda (tree)
|
|
||||||
(hang tree #f))
|
|
||||||
trees))
|
|
||||||
leaves))
|
|
||||||
|
|
||||||
(define (read-TODO file)
|
|
||||||
(hang-by-the-leaves
|
|
||||||
((make-text-outline-reader
|
|
||||||
"(([ ][ ])*)([-+])(D*)(R*)(X*)(([0-9]+)%)* *([^[]*)(\\[(.*)\\])*"
|
|
||||||
'((level-substring-divisor . 2)
|
|
||||||
(body-submatch-number . 9)
|
|
||||||
(extra-fields . ((status . 3)
|
|
||||||
(design? . 4)
|
|
||||||
(review? . 5)
|
|
||||||
(extblock? . 6)
|
|
||||||
(pct-done . 8)
|
|
||||||
(who . 11)))))
|
|
||||||
(open-file file "r"))))
|
|
||||||
|
|
||||||
(define (select-items p items)
|
|
||||||
(let ((sub '()))
|
|
||||||
(cond ((option-ref p 'involved #f)
|
|
||||||
=> (lambda (u)
|
|
||||||
(let ((u (string->symbol u)))
|
|
||||||
(set! sub (cons
|
|
||||||
(lambda (x)
|
|
||||||
(and (get x 'who)
|
|
||||||
(memq u (get x 'who))))
|
|
||||||
sub))))))
|
|
||||||
(cond ((option-ref p 'personal #f)
|
|
||||||
=> (lambda (u)
|
|
||||||
(let ((u (string->symbol u)))
|
|
||||||
(set! sub (cons
|
|
||||||
(lambda (x)
|
|
||||||
(cond ((get x 'who)
|
|
||||||
=> (lambda (ls)
|
|
||||||
(eq? (car (reverse ls))
|
|
||||||
u)))
|
|
||||||
(else #f)))
|
|
||||||
sub))))))
|
|
||||||
(for-each (lambda (pair)
|
|
||||||
(cond ((option-ref p (car pair) #f)
|
|
||||||
(set! sub (cons (cdr pair) sub)))))
|
|
||||||
`((todo . ,(lambda (x) (string=? (get x 'status) "-")))
|
|
||||||
(done . ,(lambda (x) (string=? (get x 'status) "+")))
|
|
||||||
(review . ,(lambda (x) (get x 'review?)))))
|
|
||||||
(let loop ((sub (reverse sub)) (items items))
|
|
||||||
(if (null? sub)
|
|
||||||
(reverse items)
|
|
||||||
(loop (cdr sub) (remove-if-not (car sub) items))))))
|
|
||||||
|
|
||||||
(define (make-display-item show-who? show-parent?)
|
|
||||||
(let ((show-who
|
|
||||||
(if show-who?
|
|
||||||
(lambda (item)
|
|
||||||
(cond ((get item 'who)
|
|
||||||
=> (lambda (who) (format #f " ~A" who)))
|
|
||||||
(else "")))
|
|
||||||
(lambda (item) "")))
|
|
||||||
(show-parents
|
|
||||||
(if show-parent?
|
|
||||||
(lambda (item)
|
|
||||||
(let loop ((parent (get item 'parent)) (indent 2))
|
|
||||||
(and parent
|
|
||||||
(begin
|
|
||||||
(format #t "under : ~A~A\n"
|
|
||||||
(make-string indent #\space)
|
|
||||||
parent)
|
|
||||||
(loop (get parent 'parent) (+ 2 indent))))))
|
|
||||||
(lambda (item) #t))))
|
|
||||||
(lambda (item)
|
|
||||||
(format #t "status: ~A~A~A~A~A~A\nitem : ~A\n"
|
|
||||||
(get item 'status)
|
|
||||||
(if (get item 'design?) "D" "")
|
|
||||||
(if (get item 'review?) "R" "")
|
|
||||||
(if (get item 'extblock?) "X" "")
|
|
||||||
(cond ((get item 'pct-done)
|
|
||||||
=> (lambda (pct-done)
|
|
||||||
(format #f " ~A%" pct-done)))
|
|
||||||
(else ""))
|
|
||||||
(show-who item)
|
|
||||||
item)
|
|
||||||
(show-parents item))))
|
|
||||||
|
|
||||||
(define (display-items p items)
|
|
||||||
(let ((display-item (make-display-item (option-ref p 'who #f)
|
|
||||||
(not (option-ref p 'no-parent #f))
|
|
||||||
)))
|
|
||||||
(for-each display-item items)))
|
|
||||||
|
|
||||||
(define (summarize-guile-TODO . args)
|
|
||||||
(let ((p (getopt-long (cons "summarize-guile-TODO" args)
|
|
||||||
'((who (single-char #\w))
|
|
||||||
(no-parent (single-char #\n))
|
|
||||||
(involved (single-char #\i)
|
|
||||||
(value #t))
|
|
||||||
(personal (single-char #\p)
|
|
||||||
(value #t))
|
|
||||||
(todo (single-char #\t))
|
|
||||||
(done (single-char #\d))
|
|
||||||
(review (single-char #\r))
|
|
||||||
;; Add options here.
|
|
||||||
))))
|
|
||||||
(display-items p (select-items p (read-TODO (car (option-ref p '() #f))))))
|
|
||||||
#t) ; exit val
|
|
||||||
|
|
||||||
(define main summarize-guile-TODO)
|
|
||||||
|
|
||||||
;;; summarize-guile-TODO ends here
|
|
Loading…
Add table
Add a link
Reference in a new issue