code:
;;;; benchmark-suite/lib.scm --- generic support for benchmarking
;;;; Copyright (C) 2002, 2006 Free Software Foundation, Inc.
;;;;
;;;; This program 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 3, 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 Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this software; see the file COPYING.LESSER.
;;;; If not, write to the Free Software Foundation, Inc., 51 Franklin
;;;; Street, Fifth Floor, Boston, MA 02110-1301 USA

(define-module (benchmark-suite lib)
  :export (

 ;; Controlling the execution.
 iteration-factor
 scale-iterations

 ;; Running benchmarks.
 run-benchmark
 benchmark

 ;; Naming groups of benchmarks in a regular fashion.
 with-benchmark-prefix with-benchmark-prefix* current-benchmark-prefix
 format-benchmark-name

 ;; Computing timing results
 benchmark-time-base
 benchmark-total-time benchmark-user-time benchmark-system-time
 benchmark-frame-time benchmark-core-time
 benchmark-user-time\interpreter benchmark-core-time\interpreter

 ;; Reporting results in various ways.
 register-reporter unregister-reporter reporter-registered?
 make-log-reporter
 full-reporter
 user-reporter))

;;;; If you're using Emacs's Scheme mode:
;;;;   (put 'with-benchmark-prefix 'scheme-indent-function 1)
;;;;   (put 'benchmark 'scheme-indent-function 1)

;;;; CORE FUNCTIONS
;;;;
;;;; The function (run-benchmark name iterations thunk) is the heart of the
;;;; benchmarking environment.  The first parameter NAME is a unique name for
;;;; the benchmark to be executed (for an explanation of this parameter see
;;;; below under ;;;; NAMES.  The second parameter ITERATIONS is a positive
;;;; integer value that indicates how often the thunk shall be executed (for
;;;; an explanation of how iteration counts should be used, see below under
;;;; ;;;; ITERATION COUNTS).  For example:
;;;;
;;;;    (run-benchmark "small integer addition" 100000 (lambda () (+ 1 1)))
;;;;
;;;; This will run the function (lambda () (+ 1 1)) a 100000 times (the
;;;; iteration count can, however be scaled.  See below for details).  Some
;;;; different time data for running the thunk for the given number of
;;;; iterations is measured and reported.
;;;;
;;;; Convenience macro
;;;;
;;;; * (benchmark name iterations body) is a short form for
;;;;   (run-benchmark name iterations (lambda () body))

;;;; NAMES
;;;;
;;;; Every benchmark in the benchmark suite has a unique name to be able to
;;;; compare the results of individual benchmarks across several runs of the
;;;; benchmark suite.
;;;;
;;;; A benchmark name is a list of printable objects.  For example:
;;;; ("ports.scm" "file" "read and write back list of strings")
;;;; ("ports.scm" "pipe" "read")
;;;;
;;;; Benchmark names may contain arbitrary objects, but they always have
;;;; the following properties:
;;;; - Benchmark names can be compared with EQUAL?.
;;;; - Benchmark names can be reliably stored and retrieved with the standard
;;;;   WRITE and READ procedures; doing so preserves their identity.
;;;;
;;;; For example:
;;;;
;;;;    (benchmark "simple addition" 100000 (+ 2 2))
;;;;
;;;; In that case, the benchmark name is the list ("simple addition").
;;;;
;;;; The WITH-BENCHMARK-PREFIX syntax and WITH-BENCHMARK-PREFIX* procedure
;;;; establish a prefix for the names of all benchmarks whose results are
;;;; reported within their dynamic scope.  For example:
;;;;
;;;; (begin
;;;;   (with-benchmark-prefix "basic arithmetic"
;;;;     (benchmark "addition" 100000 (+ 2 2))
;;;;     (benchmark "subtraction" 100000 (- 4 2)))
;;;;   (benchmark "multiplication" 100000 (* 2 2))))
;;;;
;;;; In that example, the three benchmark names are:
;;;;   ("basic arithmetic" "addition"),
;;;;   ("basic arithmetic" "subtraction"), and
;;;;   ("multiplication").
;;;;
;;;; WITH-BENCHMARK-PREFIX can be nested.  Each WITH-BENCHMARK-PREFIX
;;;; postpends a new element to the current prefix:
;;;;
;;;; (with-benchmark-prefix "arithmetic"
;;;;   (with-benchmark-prefix "addition"
;;;;     (benchmark "integer" 100000 (+ 2 2))
;;;;     (benchmark "complex" 100000 (+ 2+3i 4+5i)))
;;;;   (with-benchmark-prefix "subtraction"
;;;;     (benchmark "integer" 100000 (- 2 2))
;;;;     (benchmark "complex" 100000 (- 2+3i 1+2i))))
;;;;
;;;; The four benchmark names here are:
;;;;   ("arithmetic" "addition" "integer")
;;;;   ("arithmetic" "addition" "complex")
;;;;   ("arithmetic" "subtraction" "integer")
;;;;   ("arithmetic" "subtraction" "complex")
;;;;
;;;; To print a name for a human reader, we DISPLAY its elements,
;;;; separated by ": ".  So, the last set of benchmark names would be
;;;; reported as:
;;;;
;;;;   arithmetic: addition: integer
;;;;   arithmetic: addition: complex
;;;;   arithmetic: subtraction: integer
;;;;   arithmetic: subtraction: complex
;;;;
;;;; The Guile benchmarks use with-benchmark-prefix to include the name of
;;;; the source file containing the benchmark in the benchmark name, to
;;;; provide each file with its own namespace.

;;;; ITERATION COUNTS
;;;;
;;;; Every benchmark has to be given an iteration count that indicates how
;;;; often it should be executed.  The reason is, that in most cases a single
;;;; execution of the benchmark code would not deliver usable timing results:
;;;; The resolution of the system time is not arbitrarily fine.  Thus, some
;;;; benchmarks would be executed too quickly to be measured at all.  A rule
;;;; of thumb is, that the longer a benchmark runs, the more exact is the
;;;; information about the execution time.
;;;;
;;;; However, execution time depends on several influences:  First, the
;;;; machine you are running the benchmark on.  Second, the compiler you use.
;;;; Third, which compiler options you use.  Fourth, which version of guile
;;;; you are using.  Fifth, which guile options you are using (for example if
;;;; you are using the debugging evaluator or not).  There are even more
;;;; influences.
;;;;
;;;; For this reason, the same number of iterations for a single benchmark may
;;;; lead to completely different execution times in different
;;;; constellations.  For someone working on a slow machine, the default
;;;; execution counts may lead to an inacceptable execution time of the
;;;; benchmark suite.  For someone on a very fast machine, however, it may be
;;;; desireable to increase the number of iterations in order to increase the
;;;; accuracy of the time data.
;;;;
;;;; For this reason, the benchmark suite allows to scale the number of
;;;; executions by a global factor, stored in the exported variable
;;;; iteration-factor.  The default for iteration-factor is 1.  A number of 2
;;;; means, that all benchmarks are executed twice as often, which will also
;;;; roughly double the execution time for the benchmark suite.  Similarly, if
;;;; iteration-factor holds a value of 0.5, only about half the execution time
;;;; will be required.
;;;;
;;;; It is probably a good idea to choose the iteration count for each
;;;; benchmark such that all benchmarks will take about the same time, for
;;;; example one second.  To achieve this, the benchmark suite holds an empty
;;;; benchmark in the file 0-reference.bm named "reference benchmark for
;;;; iteration counts".  It's iteration count is calibrated to make the
;;;; benchmark run about one second on Dirk's laptop :-)  If you are adding
;;;; benchmarks to the suite, it would be nice if you could calibrate the
;;;; number of iterations such that each of your added benchmarks takes about
;;;; as long to run as the reference benchmark.  But:  Don't be too accurate
;;;; to figure out the correct iteration count.

;;;; REPORTERS
;;;;
;;;; A reporter is a function which we apply to each benchmark outcome.
;;;; Reporters can log results, print interesting results to the standard
;;;; output, collect statistics, etc.
;;;;
;;;; A reporter function takes the following arguments:  NAME ITERATIONS
;;;; BEFORE AFTER GC-TIME.  The argument NAME holds the name of the benchmark,
;;;; ITERATIONS holds the actual number of iterations that were performed.
;;;; BEFORE holds the result of the function (times) at the very beginning of
;;;; the excution of the benchmark, AFTER holds the result of the function
;;;; (times) after the execution of the benchmark.  GC-TIME, finally, holds
;;;; the difference of calls to (gc-run-time) before and after the execution
;;;; of the benchmark.
;;;;
;;;; This library provides some standard reporters for logging results
;;;; to a file, reporting interesting results to the user, (FIXME: and
;;;; collecting totals).
;;;;
;;;; You can use the REGISTER-REPORTER function and friends to add whatever
;;;; reporting functions you like.  See under ;;;; TIMING DATA to see how the
;;;; library helps you to extract relevant timing information from the values
;;;; ITERATIONS, BEFORE, AFTER and GC-TIME.  If you don't register any
;;;; reporters, the library uses USER-REPORTER, which writes the most
;;;; interesting results to the standard output.

;;;; TIME CALCULATION
;;;;
;;;; The library uses the guile functions (times) and (gc-run-time) to
;;;; determine the execution time for a single benchmark.  Based on these
;;;; functions, the values of BEFORE, AFTER and GC-TIME are computed, which
;;;; are then passed to the reporter functions.  All three values BEFORE,
;;;; AFTER and GC-TIME include the time needed to executed the benchmark code
;;;; itself, but also the surrounding code that implements the loop to run the
;;;; benchmark code for the given number of times.  This is undesirable, since
;;;; one would prefer to only get the timing data for the benchmarking code.
;;;;
;;;; To cope with this, the benchmarking framework uses a trick:  During
;;;; initialization of the library, the time for executing an empty benchmark
;;;; is measured and stored.  This is an estimate for the time needed by the
;;;; benchmarking framework itself.  For later benchmarks, this time can then
;;;; be subtracted from the measured execution times.
;;;;
;;;; In order to simplify the time calculation for users who want to write
;;;; their own reporters, benchmarking framework provides the following
;;;; definitions:
;;;;
;;;; benchmark-time-base : This variable holds the number of time units that
;;;;     make up a second.  By deviding the results of each of the functions
;;;;     below by this value, you get the corresponding time in seconds.  For
;;;;     example (/ (benchmark-total-time before after) benchmark-time-base)
;;;;     will give you the total time in seconds.
;;;; benchmark-total-time : this function takes two arguments BEFORE and AFTER
;;;;     and computes the total time between the two timestamps.  The result
;;;;     of this function is what the time command of the unix command line
;;;;     would report as real time.
;;;; benchmark-user-time : this function takes two arguments BEFORE and AFTER
;;;;     and computes the time spent in the benchmarking process between the
;;;;     two timestamps.  That means, the time consumed by other processes
;;;;     running on the same machine is not part of the resulting time,
;;;;     neither is time spent within the operating system.  The result of
;;;;     this function is what the time command of the unix command line would
;;;;     report as user time.
;;;; benchmark-system-time : similar to benchmark-user-time, but here the time
;;;;     spent within the operating system is given.  The result of this
;;;;     function is what the time command of the unix command line would
;;;;     report as system time.
;;;; benchmark-frame-time : this function takes the argument ITERATIONS.  It
;;;;     reports the part of the user time that is consumed by the
;;;;     benchmarking framework itself to run some benchmark for the given
;;;;     number of iterations.  You can think of this as the time that would
;;;;     still be consumed, even if the benchmarking code itself was empty.
;;;;     This value does not include any time for garbage collection, even if
;;;;     it is the benchmarking framework which is responsible for causing a
;;;;     garbage collection.
;;;; benchmark-core-time : this function takes three arguments ITERATIONS,
;;;;     BEFORE and AFTER.  It reports the part of the user time that is
;;;;     actually spent within the benchmarking code.  That is, the time
;;;;     needed for the benchmarking framework is subtracted from the user
;;;;     time.  This value, however, includes all garbage collection times,
;;;;     even if some part of the gc-time had actually to be attributed to the
;;;;     benchmarking framework.
;;;; benchmark-user-time\interpreter : this function takes three arguments
;;;;     BEFORE AFTER and GC-TIME.  It reports the part of the user time that
;;;;     is spent in the interpreter (and not in garbage collection).
;;;; benchmark-core-time\interpreter : this function takes four arguments
;;;;     ITERATIONS, BEFORE, AFTER.   and GC-TIME.  It reports the part of the
;;;;     benchmark-core-time that is spent in the interpreter (and not in
;;;;     garbage collection).  This value is most probably the one you are
;;;;     interested in, except if you are doing some garbage collection
;;;;     checks.
;;;;
;;;; There is no function to calculate the garbage-collection time, since the
;;;; garbage collection time is already passed as an argument GC-TIME to the
;;;; reporter functions.

;;;; MISCELLANEOUS
;;;;

;;; Perform a division and convert the result to inexact.
(define (i/ a b)
  (exact->inexact (/ a b)))

;;; Scale the number of iterations according to the given scaling factor.
(define iteration-factor 1)
(define (scale-iterations iterations)
  (let* ((i (inexact->exact (round (* iterations iteration-factor)))))
    (if (< i 1) 1 i)))

;;;; CORE FUNCTIONS
;;;;

;;; The central routine for executing benchmarks.
;;; The idea is taken from Greg, the GNUstep regression test environment.
(define run-benchmark #f)
(let ((benchmark-running #f))
  (define (local-run-benchmark name iterations thunk)
    (if benchmark-running
	(error "Nested calls to run-benchmark are not permitted.")
	(let ((benchmark-name (full-name name))
	      (iterations (scale-iterations iterations)))
	  (set! benchmark-running #t)
	  (let ((before #f) (after #f) (gc-time #f))
	    (gc)
	    (set! gc-time (gc-run-time))
	    (set! before (times))
	    (do ((i 0 (+ i 1)))
		((= i iterations))
	      (thunk))
	    (set! after (times))
	    (set! gc-time (- (gc-run-time) gc-time))
	    (report benchmark-name iterations before after gc-time))
	  (set! benchmark-running #f))))
  (set! run-benchmark local-run-benchmark))

;;; A short form for benchmarks.
(defmacro benchmark (name iterations body . rest)
  `(run-benchmark ,name ,iterations (lambda () ,body ,@rest)))

;;;; BENCHMARK NAMES
;;;;

;;;; Turn a benchmark name into a nice human-readable string.
(define (format-benchmark-name name)
  (call-with-output-string
   (lambda (port)
     (let loop ((name name)
		(separator ""))
       (if (pair? name)
	   (begin
	     (display separator port)
	     (display (car name) port)
	     (loop (cdr name) ": ")))))))

;;;; For a given benchmark-name, deliver the full name including all prefixes.
(define (full-name name)
  (append (current-benchmark-prefix) (list name)))

;;; A fluid containing the current benchmark prefix, as a list.
(define prefix-fluid (make-fluid))
(fluid-set! prefix-fluid '())
(define (current-benchmark-prefix)
  (fluid-ref prefix-fluid))

;;; Postpend PREFIX to the current name prefix while evaluting THUNK.
;;; The name prefix is only changed within the dynamic scope of the
;;; call to with-benchmark-prefix*.  Return the value returned by THUNK.
(define (with-benchmark-prefix* prefix thunk)
  (with-fluids ((prefix-fluid
		 (append (fluid-ref prefix-fluid) (list prefix))))
    (thunk)))

;;; (with-benchmark-prefix PREFIX BODY ...)
;;; Postpend PREFIX to the current name prefix while evaluating BODY ...
;;; The name prefix is only changed within the dynamic scope of the
;;; with-benchmark-prefix expression.  Return the value returned by the last
;;; BODY expression.
(defmacro with-benchmark-prefix (prefix . body)
  `(with-benchmark-prefix* ,prefix (lambda () ,@body)))

;;;; TIME CALCULATION
;;;;

(define benchmark-time-base
  internal-time-units-per-second)

(define time-base ;; short-cut, not exported
  benchmark-time-base)

(define frame-time/iteration
  "<will be set during initialization>")

(define (benchmark-total-time before after)
  (- (tms:clock after) (tms:clock before)))

(define (benchmark-user-time before after)
  (- (tms:utime after) (tms:utime before)))

(define (benchmark-system-time before after)
  (- (tms:stime after) (tms:stime before)))

(define (benchmark-frame-time iterations)
  (* iterations frame-time/iteration))

(define (benchmark-core-time iterations before after)
  (- (benchmark-user-time before after) (benchmark-frame-time iterations)))

(define (benchmark-user-time\interpreter before after gc-time)
  (- (benchmark-user-time before after) gc-time))

(define (benchmark-core-time\interpreter iterations before after gc-time)
  (- (benchmark-core-time iterations before after) gc-time))

;;;; REPORTERS
;;;;

;;; The global list of reporters.
(define reporters '())

;;; The default reporter, to be used only if no others exist.
(define default-reporter #f)

;;; Add the procedure REPORTER to the current set of reporter functions.
;;; Signal an error if that reporter procedure object is already registered.
(define (register-reporter reporter)
  (if (memq reporter reporters)
      (error "register-reporter: reporter already registered: " reporter))
  (set! reporters (cons reporter reporters)))

;;; Remove the procedure REPORTER from the current set of reporter
;;; functions.  Signal an error if REPORTER is not currently registered.
(define (unregister-reporter reporter)
  (if (memq reporter reporters)
      (set! reporters (delq! reporter reporters))
      (error "unregister-reporter: reporter not registered: " reporter)))

;;; Return true iff REPORTER is in the current set of reporter functions.
(define (reporter-registered? reporter)
  (if (memq reporter reporters) #t #f))

;;; Send RESULT to all currently registered reporter functions.
(define (report . args)
  (if (pair? reporters)
      (for-each (lambda (reporter) (apply reporter args))
		reporters)
      (apply default-reporter args)))

;;;; Some useful standard reporters:
;;;; Log reporters write all benchmark results to a given log file.
;;;; Full reporters write all benchmark results to the standard output.
;;;; User reporters write some interesting results to the standard output.

;;; Display a single benchmark result to the given port
(define (print-result port name iterations before after gc-time)
  (let* ((name (format-benchmark-name name))
	 (total-time (benchmark-total-time before after))
	 (user-time (benchmark-user-time before after))
	 (system-time (benchmark-system-time before after))
	 (frame-time (benchmark-frame-time iterations))
	 (benchmark-time (benchmark-core-time iterations before after))
	 (user-time\interpreter
	  (benchmark-user-time\interpreter before after gc-time))
	 (benchmark-core-time\interpreter
	  (benchmark-core-time\interpreter iterations before after gc-time)))
    (write (list name iterations
		 'total (i/ total-time time-base)
		 'user (i/ user-time time-base)
		 'system (i/ system-time time-base)
		 'frame (i/ frame-time time-base)
		 'benchmark (i/ benchmark-time time-base)
		 'user/interp (i/ user-time\interpreter time-base)
		 'bench/interp (i/ benchmark-core-time\interpreter time-base)
		 'gc (i/ gc-time time-base))
	   port)
    (newline port)))

;;; Return a reporter procedure which prints all results to the file
;;; FILE, in human-readable form.  FILE may be a filename, or a port.
(define (make-log-reporter file)
  (let ((port (if (output-port? file) file
		  (open-output-file file))))
    (lambda args
      (apply print-result port args)
      (force-output port))))

;;; A reporter that reports all results to the user.
(define (full-reporter . args)
  (apply print-result (current-output-port) args))

;;; Display interesting results of a single benchmark to the given port
(define (print-user-result port name iterations before after gc-time)
  (let* ((name (format-benchmark-name name))
	 (user-time (benchmark-user-time before after))
	 (benchmark-time (benchmark-core-time iterations before after))
	 (benchmark-core-time\interpreter
	  (benchmark-core-time\interpreter iterations before after gc-time)))
    (write (list name iterations
		 'user (i/ user-time time-base)
		 'benchmark (i/ benchmark-time time-base)
		 'bench/interp (i/ benchmark-core-time\interpreter time-base)
		 'gc (i/ gc-time time-base))
	   port)
    (newline port)))

;;; A reporter that reports interesting results to the user.
(define (user-reporter . args)
  (apply print-user-result (current-output-port) args))

;;;; Initialize the benchmarking system:
;;;;

;;; First, display version information
(display ";; running guile version " (current-output-port))
(display (version) (current-output-port))
(newline (current-output-port))

;;; Second, make sure the benchmarking routines are compiled.
(define (null-reporter . args) #t)
(set! default-reporter null-reporter)
(benchmark "empty initialization benchmark" 2 #t)

;;; Third, initialize the system constants
(display ";; calibrating the benchmarking framework..." (current-output-port))
(newline (current-output-port))
(define (initialization-reporter name iterations before after gc-time)
  (let* ((frame-time (- (tms:utime after) (tms:utime before) gc-time 3)))
    (set! frame-time/iteration (/ frame-time iterations))
    (display ";; framework time per iteration: " (current-output-port))
    (display (i/ frame-time/iteration time-base) (current-output-port))
    (newline (current-output-port))))
(set! default-reporter initialization-reporter)
(benchmark "empty initialization benchmark" 524288 #t)

;;; Finally, set the default reporter
(set! default-reporter user-reporter)


code:
Benchmarking /home/neil/SW/Guile/git/meta/guile ...
with GUILE_LOAD_PATH=/home/neil/SW/Guile/git/benchmark-suite
;; running guile version 1.9.3
;; calibrating the benchmarking framework...
;; framework time per iteration: 5.7220458984375e-7
("0-reference.bm: reference benchmark for iteration counts" 330000 user 0.2 benchmark 0.0111724853515625 bench/interp 0.0111724853515625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u8-ref" 1000000 user 0.73 benchmark 0.15779541015625 bench/interp 0.15779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u16-ref (foreign)" 1000000 user 0.82 benchmark 0.24779541015625 bench/interp 0.24779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u16-ref (native)" 1000000 user 0.78 benchmark 0.20779541015625 bench/interp 0.20779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u16-native-ref" 1000000 user 0.72 benchmark 0.14779541015625 bench/interp 0.14779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u32-ref (foreign)" 1000000 user 1.61 benchmark 1.03779541015625 bench/interp 1.03779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u32-ref (native)" 1000000 user 0.8 benchmark 0.22779541015625 bench/interp 0.22779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u32-native-ref" 1000000 user 0.74 benchmark 0.16779541015625 bench/interp 0.16779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u64-ref (foreign)" 1000000 user 1.86 benchmark 1.28779541015625 bench/interp 1.28779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u64-ref (native)" 1000000 user 0.81 benchmark 0.23779541015625 bench/interp 0.23779541015625 gc 0.0)
("bytevectors.bm: ref/set!: bytevector-u64-native-ref" 1000000 user 0.73 benchmark 0.15779541015625 bench/interp 0.15779541015625 gc 0.0)
("bytevectors.bm: lists: bytevector->u8-list" 2000 user 9.87 benchmark 9.86885559082031 bench/interp 9.86885559082031 gc 0.0)
("bytevectors.bm: lists: bytevector->uint-list 16-bit" 2000 user 4.48 benchmark 4.47885559082031 bench/interp 4.47885559082031 gc 0.0)
("bytevectors.bm: lists: bytevector->uint-list 64-bit" 2000 user 3.75 benchmark 3.74885559082031 bench/interp 3.74885559082031 gc 0.0)
("bytevectors.bm: SRFI-4: u8vector-ref" 1000000 user 1.88 benchmark 1.30779541015625 bench/interp 1.30779541015625 gc 0.0)
("bytevectors.bm: SRFI-4: u16vector-ref" 1000000 user 1.9 benchmark 1.32779541015625 bench/interp 1.32779541015625 gc 0.0)
("bytevectors.bm: SRFI-4: u32vector-ref" 1000000 user 1.88 benchmark 1.30779541015625 bench/interp 1.30779541015625 gc 0.0)
("bytevectors.bm: SRFI-4: u64vector-ref" 1000000 user 1.98 benchmark 1.40779541015625 bench/interp 1.40779541015625 gc 0.0)
("chars.bm: chars: char" 1000000 user 0.63 benchmark 0.05779541015625 bench/interp 0.05779541015625 gc 0.0)
("chars.bm: chars: octal" 1000000 user 0.64 benchmark 0.06779541015625 bench/interp 0.06779541015625 gc 0.0)
("chars.bm: chars: char? eq" 1000000 user 1.19 benchmark 0.61779541015625 bench/interp 0.61779541015625 gc 0.0)
("chars.bm: chars: char=?" 1000000 user 1.45 benchmark 0.87779541015625 bench/interp 0.87779541015625 gc 0.0)
("chars.bm: chars: char<?" 1000000 user 1.45 benchmark 0.87779541015625 bench/interp 0.87779541015625 gc 0.0)
("chars.bm: chars: char-ci=?" 1000000 user 1.45 benchmark 0.87779541015625 bench/interp 0.87779541015625 gc 0.0)
("chars.bm: chars: char-ci<? " 1000000 user 1.45 benchmark 0.87779541015625 bench/interp 0.87779541015625 gc 0.0)
("chars.bm: chars: char->integer" 1000000 user 1.2 benchmark 0.62779541015625 bench/interp 0.62779541015625 gc 0.0)
("chars.bm: chars: char-alphabetic?" 1000000 user 1.36 benchmark 0.78779541015625 bench/interp 0.78779541015625 gc 0.0)
("chars.bm: chars: char-numeric?" 1000000 user 1.36 benchmark 0.78779541015625 bench/interp 0.78779541015625 gc 0.0)
("continuations.bm: call/cc" 300 user 0.03 benchmark 0.0298283386230469 bench/interp 0.0298283386230469 gc 0.0)
("if.bm: if-<expr>-then-else: executing then" 330000 user 0.23 benchmark 0.0411724853515625 bench/interp 0.0411724853515625 gc 0.0)
("if.bm: if-<expr>-then-else: executing else" 330000 user 0.23 benchmark 0.0411724853515625 bench/interp 0.0411724853515625 gc 0.0)
("if.bm: if-<expr>-then: executing then" 330000 user 0.23 benchmark 0.0411724853515625 bench/interp 0.0411724853515625 gc 0.0)
("if.bm: if-<expr>-then: executing else" 330000 user 0.24 benchmark 0.0511724853515625 bench/interp 0.0511724853515625 gc 0.0)
("if.bm: if-<iloc>-then-else: executing then" 330000 user 0.25 benchmark 0.0611724853515625 bench/interp 0.0611724853515625 gc 0.0)
("if.bm: if-<iloc>-then-else: executing else" 330000 user 0.24 benchmark 0.0511724853515625 bench/interp 0.0511724853515625 gc 0.0)
("if.bm: if-<iloc>-then: executing then" 330000 user 0.24 benchmark 0.0511724853515625 bench/interp 0.0511724853515625 gc 0.0)
("if.bm: if-<iloc>-then: executing else" 330000 user 0.24 benchmark 0.0511724853515625 bench/interp 0.0511724853515625 gc 0.0)
("if.bm: if-<bool>-then-else: executing then" 330000 user 0.23 benchmark 0.0411724853515625 bench/interp 0.0411724853515625 gc 0.0)
("if.bm: if-<bool>-then-else: executing else" 330000 user 0.23 benchmark 0.0411724853515625 bench/interp 0.0411724853515625 gc 0.0)
("if.bm: if-<bool>-then: executing then" 330000 user 0.24 benchmark 0.0511724853515625 bench/interp 0.0511724853515625 gc 0.0)
("if.bm: if-<bool>-then: executing else" 330000 user 0.23 benchmark 0.0411724853515625 bench/interp 0.0411724853515625 gc 0.0)
("logand.bm: bignum" 130000 user 0.48 benchmark 0.405613403320312 bench/interp 0.405613403320312 gc 0.0)
("read.bm: read: _IONBF" 5 user 12.71 benchmark 12.7099971389771 bench/interp 12.7099971389771 gc 0.0)
("read.bm: read: _IOLBF" 10 user 20.32 benchmark 20.3199942779541 bench/interp 20.3199942779541 gc 0.0)
("read.bm: read: _IOFBF 4096" 10 user 20.34 benchmark 20.3399942779541 bench/interp 20.3399942779541 gc 0.0)
("read.bm: read: _IOFBF 8192" 10 user 20.36 benchmark 20.3599942779541 bench/interp 20.3599942779541 gc 0.0)
("read.bm: read: _IOFBF 16384" 10 user 20.34 benchmark 20.3399942779541 bench/interp 20.3399942779541 gc 0.0)
("srfi-13.bm: strings: predicates: string?" 1190000 user 2.98 benchmark 2.29907653808594 bench/interp 2.29907653808594 gc 0.0)
("srfi-13.bm: strings: predicates: null?" 969000 user 2.56 benchmark 2.00553375244141 bench/interp 2.00553375244141 gc 0.0)
("srfi-13.bm: strings: predicates: any" 94000 user 1.89 benchmark 1.83621276855469 bench/interp 1.83621276855469 gc 0.0)
("srfi-13.bm: strings: predicates: every" 94000 user 1.53 benchmark 1.47621276855469 bench/interp 1.47621276855469 gc 0.0)
("srfi-13.bm: strings: constructors: string" 5000 user 2.02 benchmark 2.01713897705078 bench/interp 2.01713897705078 gc 0.0)
("srfi-13.bm: strings: constructors: list->" 4500 user 0.3 benchmark 0.297425079345703 bench/interp 0.297425079345703 gc 0.0)
("srfi-13.bm: strings: constructors: reverse-list->" 5000 user 0.58 benchmark 0.577138977050781 bench/interp 0.577138977050781 gc 0.0)
("srfi-13.bm: strings: constructors: make" 22000 user 0.52 benchmark 0.507411499023438 bench/interp 0.507411499023438 gc 0.0)
("srfi-13.bm: strings: constructors: tabulate" 17000 user 0.57 benchmark 0.560272521972656 bench/interp 0.560272521972656 gc 0.0)
("srfi-13.bm: strings: constructors: join" 5500 user 0.46 benchmark 0.456852874755859 bench/interp 0.456852874755859 gc 0.0)
("srfi-13.bm: strings: list/string: ->list" 7300 user 2.36 benchmark 2.35582290649414 bench/interp 2.35582290649414 gc 0.0)
("srfi-13.bm: strings: list/string: split" 60000 user 1.87 benchmark 1.83566772460938 bench/interp 1.83566772460938 gc 0.0)
("srfi-13.bm: strings: selection: ref" 660 user 1.5 benchmark 1.4996223449707 bench/interp 1.4996223449707 gc 0.0)
("srfi-13.bm: strings: selection: copy" 1100 user 0.04 benchmark 0.0393705749511719 bench/interp 0.0393705749511719 gc 0.0)
("srfi-13.bm: strings: selection: pad" 6800 user 0.17 benchmark 0.166109008789063 bench/interp 0.166109008789063 gc 0.0)
("srfi-13.bm: strings: selection: trim trim-right trim-both" 60000 user 2.67 benchmark 2.63566772460937 bench/interp 2.63566772460937 gc 0.0)
("srfi-13.bm: strings: modification: set!" 3000 user 1.42 benchmark 1.41828338623047 bench/interp 1.41828338623047 gc 0.0)
("srfi-13.bm: strings: modification: sub-move!" 230000 user 1.88 benchmark 1.74839294433594 bench/interp 1.74839294433594 gc 0.0)
("srfi-13.bm: strings: modification: fill!" 230000 user 2.31 benchmark 2.17839294433594 bench/interp 2.17839294433594 gc 0.0)
("srfi-13.bm: strings: modification: comparison: compare compare-ci" 140000 user 1.93 benchmark 1.84989135742187 bench/interp 1.84989135742187 gc 0.0)
("srfi-13.bm: strings: modification: comparison: hash hash-ci" 1000 user 0.27 benchmark 0.269427795410156 bench/interp 0.269427795410156 gc 0.0)
("srfi-13.bm: strings: searching: prefix-length suffix-length" 270 user 0.2 benchmark 0.199845504760742 bench/interp 0.199845504760742 gc 0.0)
("srfi-13.bm: strings: searching: prefix? suffix?" 270 user 0.2 benchmark 0.199845504760742 bench/interp 0.199845504760742 gc 0.0)
("srfi-13.bm: strings: searching: index index-right rindex" 100000 user 3.48 benchmark 3.42277954101562 bench/interp 3.42277954101562 gc 0.0)
("srfi-13.bm: strings: searching: skip skip-right?" 100000 user 2.14 benchmark 2.08277954101563 bench/interp 2.08277954101563 gc 0.0)
("srfi-13.bm: strings: searching: count" 10000 user 9.35 benchmark 9.34427795410156 bench/interp 9.34427795410156 gc 0.0)
("srfi-13.bm: strings: searching: contains contains-ci" 34000 user 2.29 benchmark 2.27054504394531 bench/interp 2.27054504394531 gc 0.0)
("srfi-13.bm: strings: searching: upcase downcase upcase! downcase!" 600 user 0.2 benchmark 0.199656677246094 bench/interp 0.199656677246094 gc 0.0)
("srfi-13.bm: strings: readers: read token, method 1" 1200 user 1.26 benchmark 1.25931335449219 bench/interp 1.25931335449219 gc 0.0)
("srfi-13.bm: strings: readers: read token, method 2" 1200 user 2.03 benchmark 2.02931335449219 bench/interp 2.02931335449219 gc 0.0)
("subr.bm: subr invocation: simple subr" 700000 user 0.47 benchmark 0.069456787109375 bench/interp 0.069456787109375 gc 0.0)
("subr.bm: subr invocation: generic subr" 700000 user 1.75 benchmark 1.34945678710938 bench/interp 1.34945678710938 gc 0.0)
("subr.bm: subr invocation: generic subr with rest arg" 700000 user 1.39 benchmark 0.989456787109375 bench/interp 0.989456787109375 gc 0.0)
("subr.bm: subr invocation: generic subr with rest arg and 3+ parameters" 700000 user 1.86 benchmark 1.45945678710938 bench/interp 1.45945678710938 gc 0.0)
("subr.bm: subr application: simple subr" 700000 user 0.91 benchmark 0.509456787109375 bench/interp 0.509456787109375 gc 0.0)
("subr.bm: subr application: generic subr" 700000 user 1.8 benchmark 1.39945678710938 bench/interp 1.39945678710938 gc 0.0)
("subr.bm: subr application: generic subr with rest arg" 700000 user 1.44 benchmark 1.03945678710937 bench/interp 1.03945678710937 gc 0.0)
("subr.bm: subr application: generic subr with rest arg and 3+ parameters" 700000 user 1.89 benchmark 1.48945678710937 bench/interp 1.48945678710937 gc 0.0)
("uniform-vector-read.bm: uniform-vector-read!: uniform-vector-write" 500 user 0.12 benchmark 0.119713897705078 bench/interp 0.119713897705078 gc 0.0)
("uniform-vector-read.bm: uniform-vector-read!: uniform-vector-read!" 500 user 0.02 benchmark 0.0197138977050781 bench/interp 0.0197138977050781 gc 0.0)
("uniform-vector-read.bm: uniform-vector-read!: string port" 5000 user 2.49 benchmark 2.48713897705078 bench/interp 2.48713897705078 gc 0.0)

path: benchmark-suite/results/neil-arudy

license: mit


code:
;; -*- Scheme -*-
;;
;; A library of dumb functions that may be used to benchmark Guile-VM.

;; The comments are from Ludovic, a while ago. The speedups now are much
;; more significant (all over 2x, sometimes 8x).

(define (fibo x)
  (if (or (= x 1) (= x 2))
      1
      (+ (fibo (- x 1))
	 (fibo (- x 2)))))

(define (g-c-d x y)
  (if (= x y)
      x
      (if (< x y)
	  (g-c-d x (- y x))
	  (g-c-d (- x y) y))))

(define (loop n)
  ;; This one shows that procedure calls are no faster than within the
  ;; interpreter: the VM yields no performance improvement.
  (if (= 0 n)
      0
      (loop (1- n))))

;; Disassembly of `loop'
;;
;; Disassembly of #<objcode b79bdf28>:

;; nlocs = 0  nexts = 0

;;    0    (make-int8 64)                  ;; 64
;;    2    (load-symbol "guile-user")      ;; guile-user
;;   14    (list 0 1)                      ;; 1 element
;;   17    (load-symbol "loop")            ;; loop
;;   23    (link-later)
;;   24    (vector 0 1)                    ;; 1 element
;;   27    (make-int8 0)                   ;; 0
;;   29    (load-symbol "n")               ;; n
;;   32    (make-false)                    ;; #f
;;   33    (make-int8 0)                   ;; 0
;;   35    (list 0 3)                      ;; 3 elements
;;   38    (list 0 2)                      ;; 2 elements
;;   41    (list 0 1)                      ;; 1 element
;;   44    (make-int8 5)                   ;; 5
;;   46    (make-false)                    ;; #f
;;   47    (cons)
;;   48    (make-int8 18)                  ;; 18
;;   50    (make-false)                    ;; #f
;;   51    (cons)
;;   52    (make-int8 20)                  ;; 20
;;   54    (make-false)                    ;; #f
;;   55    (cons)
;;   56    (list 0 4)                      ;; 4 elements
;;   59    (load-program ##{66}#)
;;   81    (define "loop")
;;   87    (variable-set)
;;   88    (void)
;;   89    (return)

;; Bytecode ##{66}#:

;;    0    (make-int8 0)                   ;; 0
;;    2    (local-ref 0)
;;    4    (ee?)
;;    5    (br-if-not 0 3)                 ;; -> 11
;;    8    (make-int8 0)                   ;; 0
;;   10    (return)
;;   11    (toplevel-ref 0)
;;   13    (local-ref 0)
;;   15    (make-int8 1)                   ;; 1
;;   17    (sub)
;;   18    (tail-call 1)

(define (loopi n)
  ;; Same as `loop'.
  (let loopi ((n n))
    (if (= 0 n)
	0
	(loopi (1- n)))))

(define (do-loop n)
  ;; Same as `loop' using `do'.
  (do ((i n (1- i)))
      ((= 0 i))
    ;; do nothing
    ))

(define (do-cons x)
  ;; This one shows that the built-in `cons' instruction yields a significant
  ;; improvement (speedup: 1.5).
  (let loop ((x x)
	     (result '()))
    (if (<= x 0)
	result
	(loop (1- x) (cons x result)))))

(define big-list (iota 500000))

(define (copy-list lst)
  ;; Speedup: 5.9.
  (let loop ((lst lst)
	     (result '()))
    (if (null? lst)
	result
	(loop (cdr lst)
	      (cons (car lst) result)))))


code:
#!/bin/sh
# aside from this initial boilerplate, this is actually -*- scheme -*- code
main='(module-ref (resolve-module '\''(measure)) '\'main')'
exec ${GUILE-guile} -l $0 -c "(apply $main (cdr (command-line)))" "$@"
!#

;; A simple interpreter vs. VM performance comparison tool
;;

(define-module (measure)
  :export (measure)
  :use-module (system vm vm)
  :use-module (system base compile)
  :use-module (system base language))

(define (time-for-eval sexp eval)
  (let ((before (tms:utime (times))))
    (eval sexp)
    (let ((elapsed (- (tms:utime (times)) before)))
      (format #t "elapsed time: ~a~%" elapsed)
      elapsed)))

(define *scheme* (lookup-language 'scheme))

(define (measure . args)
  (if (< (length args) 2)
      (begin
	(format #t "Usage: measure SEXP FILE-TO-LOAD...~%")
	(format #t "~%")
	(format #t "Example: measure '(loop 23424)' lib.scm~%~%")
	(exit 1)))
  (for-each load (cdr args))
  (let* ((sexp (with-input-from-string (car args)
		 (lambda ()
		   (read))))
	 (eval-here (lambda (sexp) (eval sexp (current-module))))
	 (proc-name (car sexp))
	 (proc-source (procedure-source (eval proc-name (current-module))))
	 (% (format #t "proc: ~a~%source: ~a~%" proc-name proc-source))
	 (time-interpreted (time-for-eval sexp eval-here))
	 (& (if (defined? proc-name)
		(eval `(set! ,proc-name #f) (current-module))
		(format #t "unbound~%")))
	 (the-program (compile proc-source))

	 (time-compiled (time-for-eval `(,proc-name ,@(cdr sexp))
				       (lambda (sexp)
					 (eval `(begin
						  (define ,proc-name
						    ,the-program)
						  ,sexp)
					       (current-module))))))

    (format #t "proc:        ~a => ~a~%"
	    proc-name (eval proc-name (current-module)))
    (format #t "interpreted: ~a~%" time-interpreted)
    (format #t "compiled:    ~a~%" time-compiled)
    (format #t "speedup:     ~a~%"
	    (exact->inexact (/ time-interpreted time-compiled)))
    0))

(define main measure)


code:
eval '(exit $?0)' && eval 'exec perl -wS "$0" ${1+"$@"}'
  & eval 'exec perl -wS "$0" $argv:q'
    if 0;
# Generate a release announcement message.

my $VERSION = '2010-05-03 20:17'; # UTC
# The definition above must lie within the first 8 lines in order
# for the Emacs time-stamp write hook (at end) to update it.
# If you change this file with Emacs, please let the write hook
# do its job.  Otherwise, update this string manually.

# Copyright (C) 2002-2010 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 3 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, see <http://www.gnu.org/licenses/>.

# Written by Jim Meyering

use strict;

use Getopt::Long;
use Digest::MD5;
use Digest::SHA1;
use POSIX qw(strftime);

(my $ME = $0) =~ s|.*/||;

my %valid_release_types = map {$_ => 1} qw (alpha beta stable);
my @archive_suffixes = ('tar.gz', 'tar.bz2', 'tar.lzma', 'tar.xz');

sub usage ($)
{
  my ($exit_code) = @_;
  my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR);
  if ($exit_code != 0)
    {
      print $STREAM "Try `$ME --help' for more information.\n";
    }
  else
    {
      my @types = sort keys %valid_release_types;
      print $STREAM <<EOF;
Usage: $ME [OPTIONS]
Generate an announcement message.

OPTIONS:

These options must be specified:

   --release-type=TYPE          TYPE must be one of @types
   --package-name=PACKAGE_NAME
   --previous-version=VER
   --current-version=VER
   --gpg-key-id=ID         The GnuPG ID of the key used to sign the tarballs
   --url-directory=URL_DIR

The following are optional:

   --news=NEWS_FILE
   --bootstrap-tools=TOOL_LIST  a comma-separated list of tools, e.g.,
                                autoconf,automake,bison,gnulib
   --gnulib-version=VERSION     report VERSION as the gnulib version, where
                                VERSION is the result of running git describe
                                in the gnulib source directory.
                                required if gnulib is in TOOL_LIST.
   --no-print-checksums         do not emit MD5 or SHA1 checksums
   --archive-suffix=SUF         add SUF to the list of archive suffixes
   --mail-headers=HEADERS       a space-separated list of mail headers, e.g.,
                                To: x\@example.com Cc: y-announce\@example.com,...

   --help             display this help and exit
   --version          output version information and exit

EOF
    }
  exit $exit_code;
}

=item C<%size> = C<sizes (@file)>

Compute the sizes of the C<@file> and return them as a hash.  Return
C<undef> if one of the computation failed.

=cut

sub sizes (@)
{
  my (@file) = @_;

  my $fail = 0;
  my %res;
  foreach my $f (@file)
    {
      my $cmd = "du --human $f";
      my $t = `$cmd`;
      # FIXME-someday: give a better diagnostic, a la $PROCESS_STATUS
      $@
	and (warn "$ME: command failed: `$cmd'\n"), $fail = 1;
      chomp $t;
      $t =~ s/^([\d.]+[MkK]).*/${1}B/;
      $res{$f} = $t;
    }
  return $fail ? undef : %res;
}

=item C<print_locations ($title, \@url, \%size, @file)

Print a section C<$title> dedicated to the list of <@file>, which
sizes are stored in C<%size>, and which are available from the C<@url>.

=cut

sub print_locations ($\@\%@)
{
  my ($title, $url, $size, @file) = @_;
  print "Here are the $title:\n";
  foreach my $url (@{$url})
    {
      for my $file (@file)
	{
	  print "  $url/$file";
	  print "   (", $$size{$file}, ")"
	    if exists $$size{$file};
	  print "\n";
	}
    }
  print "\n";
}

=item C<print_checksums (@file)

Print the MD5 and SHA1 signature section for each C<@file>.

=cut

sub print_checksums (@)
{
  my (@file) = @_;

  print "Here are the MD5 and SHA1 checksums:\n";
  print "\n";

  foreach my $meth (qw (md5 sha1))
    {
      foreach my $f (@file)
	{
	  open IN, '<', $f
	    or die "$ME: $f: cannot open for reading: $!\n";
	  binmode IN;
	  my $dig =
	    ($meth eq 'md5'
	     ? Digest::MD5->new->addfile(*IN)->hexdigest
	     : Digest::SHA1->new->addfile(*IN)->hexdigest);
	  close IN;
	  print "$dig  $f\n";
	}
    }
  print "\n";
}

=item C<print_news_deltas ($news_file, $prev_version, $curr_version)

Print the section of the NEWS file C<$news_file> addressing changes
between versions C<$prev_version> and C<$curr_version>.

=cut

sub print_news_deltas ($$$)
{
  my ($news_file, $prev_version, $curr_version) = @_;

  print "\n$news_file\n\n";

  # Print all lines from $news_file, starting with the first one
  # that mentions $curr_version up to but not including
  # the first occurrence of $prev_version.
  my $in_items;

  my $re_prefix = qr/(?:\* )?(?:Noteworthy c|Major c|C)(?i:hanges)/;

  open NEWS, '<', $news_file
    or die "$ME: $news_file: cannot open for reading: $!\n";
  while (defined (my $line = <NEWS>))
    {
      if ( ! $in_items)
	{
	  # Match lines like these:
	  # * Major changes in release 5.0.1:
	  # * Noteworthy changes in release 6.6 (2006-11-22) [stable]
	  $line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$curr_version\E(?:[^\d.]|$)/o
	    or next;
	  $in_items = 1;
	  print $line;
	}
      else
	{
	  # This regexp must not match version numbers in NEWS items.
	  # For example, they might well say `introduced in 4.5.5',
	  # and we don't want that to match.
	  $line =~ /^$re_prefix.*(?:[^\d.]|$)\Q$prev_version\E(?:[^\d.]|$)/o
	    and last;
	  print $line;
	}
    }
  close NEWS;

  $in_items
    or die "$ME: $news_file: no matching lines for `$curr_version'\n";
}

sub print_changelog_deltas ($$)
{
  my ($package_name, $prev_version) = @_;

  # Print new ChangeLog entries.

  # First find all CVS-controlled ChangeLog files.
  use File::Find;
  my @changelog;
  find ({wanted => sub {$_ eq 'ChangeLog' && -d 'CVS'
			  and push @changelog, $File::Find::name}},
	'.');

  # If there are no ChangeLog files, we're done.
  @changelog
    or return;
  my %changelog = map {$_ => 1} @changelog;

  # Reorder the list of files so that if there are ChangeLog
  # files in the specified directories, they're listed first,
  # in this order:
  my @dir = qw ( . src lib m4 config doc );

  # A typical @changelog array might look like this:
  # ./ChangeLog
  # ./po/ChangeLog
  # ./m4/ChangeLog
  # ./lib/ChangeLog
  # ./doc/ChangeLog
  # ./config/ChangeLog
  my @reordered;
  foreach my $d (@dir)
    {
      my $dot_slash = $d eq '.' ? $d : "./$d";
      my $target = "$dot_slash/ChangeLog";
      delete $changelog{$target}
	and push @reordered, $target;
    }

  # Append any remaining ChangeLog files.
  push @reordered, sort keys %changelog;

  # Remove leading `./'.
  @reordered = map { s!^\./!!; $_ } @reordered;

  print "\nChangeLog entries:\n\n";
  # print join ("\n", @reordered), "\n";

  $prev_version =~ s/\./_/g;
  my $prev_cvs_tag = "\U$package_name\E-$prev_version";

  my $cmd = "cvs -n diff -u -r$prev_cvs_tag -rHEAD @reordered";
  open DIFF, '-|', $cmd
    or die "$ME: cannot run `$cmd': $!\n";
  # Print two types of lines, making minor changes:
  # Lines starting with `+++ ', e.g.,
  # +++ ChangeLog   22 Feb 2003 16:52:51 -0000      1.247
  # and those starting with `+'.
  # Don't print the others.
  my $prev_printed_line_empty = 1;
  while (defined (my $line = <DIFF>))
    {
      if ($line =~ /^\+\+\+ /)
	{
	  my $separator = "*"x70 ."\n";
	  $line =~ s///;
	  $line =~ s/\s.*//;
	  $prev_printed_line_empty
	    or print "\n";
	  print $separator, $line, $separator;
	}
      elsif ($line =~ /^\+/)
	{
	  $line =~ s///;
	  print $line;
	  $prev_printed_line_empty = ($line =~ /^$/);
	}
    }
  close DIFF;

  # The exit code should be 1.
  # Allow in case there are no modified ChangeLog entries.
  $? == 256 || $? == 128
    or warn "$ME: warning: `cmd' had unexpected exit code or signal ($?)\n";
}

sub get_tool_versions ($$)
{
  my ($tool_list, $gnulib_version) = @_;
  @$tool_list
    or return ();

  my $fail;
  my @tool_version_pair;
  foreach my $t (@$tool_list)
    {
      if ($t eq 'gnulib')
	{
	  push @tool_version_pair, ucfirst $t . ' ' . $gnulib_version;
	  next;
	}
      # Assume that the last "word" on the first line of
      # `tool --version` output is the version string.
      my ($first_line, undef) = split ("\n", `$t --version`);
      if ($first_line =~ /.* (\d[\w.-]+)$/)
	{
	  $t = ucfirst $t;
	  push @tool_version_pair, "$t $1";
	}
      else
	{
	  defined $first_line
	    and $first_line = '';
	  warn "$ME: $t: unexpected --version output\n:$first_line";
	  $fail = 1;
	}
    }

  $fail
    and exit 1;

  return @tool_version_pair;
}

{
  # Neutralize the locale, so that, for instance, "du" does not
  # issue "1,2" instead of "1.2", what confuses our regexps.
  $ENV{LC_ALL} = "C";

  my $mail_headers;
  my $release_type;
  my $package_name;
  my $prev_version;
  my $curr_version;
  my $gpg_key_id;
  my @url_dir_list;
  my @news_file;
  my $bootstrap_tools;
  my $gnulib_version;
  my $print_checksums_p = 1;

  GetOptions
    (
     'mail-headers=s'     => \$mail_headers,
     'release-type=s'     => \$release_type,
     'package-name=s'     => \$package_name,
     'previous-version=s' => \$prev_version,
     'current-version=s'  => \$curr_version,
     'gpg-key-id=s'       => \$gpg_key_id,
     'url-directory=s'    => \@url_dir_list,
     'news=s'             => \@news_file,
     'bootstrap-tools=s'  => \$bootstrap_tools,
     'gnulib-version=s'   => \$gnulib_version,
     'print-checksums!'   => \$print_checksums_p,
     'archive-suffix=s'   => \@archive_suffixes,

     help => sub { usage 0 },
     version => sub { print "$ME version $VERSION\n"; exit },
    ) or usage 1;

  my $fail = 0;
  # Ensure that sure each required option is specified.
  $release_type
    or (warn "$ME: release type not specified\n"), $fail = 1;
  $package_name
    or (warn "$ME: package name not specified\n"), $fail = 1;
  $prev_version
    or (warn "$ME: previous version string not specified\n"), $fail = 1;
  $curr_version
    or (warn "$ME: current version string not specified\n"), $fail = 1;
  $gpg_key_id
    or (warn "$ME: GnuPG key ID not specified\n"), $fail = 1;
  @url_dir_list
    or (warn "$ME: URL directory name(s) not specified\n"), $fail = 1;

  my @tool_list = split ',', $bootstrap_tools;

  grep (/^gnulib$/, @tool_list) ^ defined $gnulib_version
    and (warn "$ME: when specifying gnulib as a tool, you must also specify\n"
	. "--gnulib-version=V, where V is the result of running git describe\n"
	. "in the gnulib source directory.\n"), $fail = 1;

  exists $valid_release_types{$release_type}
    or (warn "$ME: `$release_type': invalid release type\n"), $fail = 1;

  @ARGV
    and (warn "$ME: too many arguments:\n", join ("\n", @ARGV), "\n"),
      $fail = 1;
  $fail
    and usage 1;

  my $my_distdir = "$package_name-$curr_version";

  my $xd = "$package_name-$prev_version-$curr_version.xdelta";

  my @candidates = map { "$my_distdir.$_" } @archive_suffixes;
  my @tarballs = grep {-f $_} @candidates;

  @tarballs
    or die "$ME: none of " . join(', ', @candidates) . " were found\n";
  my @sizable = @tarballs;
  -f $xd
    and push @sizable, $xd;
  my %size = sizes (@sizable);
  %size
    or exit 1;

  my $headers = '';
  if (defined $mail_headers)
    {
      ($headers = $mail_headers) =~ s/\s+(\S+:)/\n$1/g;
      $headers .= "\n";
    }

  # The markup is escaped as <\# so that when this script is sent by
  # mail (or part of a diff), Gnus is not triggered.
  print <<EOF;

${headers}Subject: $my_distdir released [$release_type]

<\#secure method=pgpmime mode=sign>

FIXME: put comments here

EOF

  print_locations ("compressed sources", @url_dir_list, %size, @tarballs);
  -f $xd
    and print_locations ("xdelta diffs (useful? if so, "
			 . "please tell bug-gnulib\@gnu.org)",
			 @url_dir_list, %size, $xd);
  my @sig_files = map { "$_.sig" } @tarballs;
  print_locations ("GPG detached signatures[*]", @url_dir_list, %size,
		   @sig_files);
  if ($url_dir_list[0] =~ "gnu\.org")
    {
      print "To reduce load on the main server, use a mirror listed at:\n";
      print "  http://www.gnu.org/order/ftp.html\n\n";
    }

  $print_checksums_p
    and print_checksums (@sizable);

  print <<EOF;
[*] You can use either of the above signature files to verify that
the corresponding file (without the .sig suffix) is intact.  First,
be sure to download both the .sig file and the corresponding tarball.
Then, run a command like this:

  gpg --verify $tarballs[0].sig

If that command fails because you don't have the required public key,
then run this command to import it:

  gpg --keyserver keys.gnupg.net --recv-keys $gpg_key_id

and rerun the \`gpg --verify' command.
EOF

  my @tool_versions = get_tool_versions (\@tool_list, $gnulib_version);
  @tool_versions
    and print "\nThis release was bootstrapped with the following tools:",
      join ('', map {"\n  $_"} @tool_versions), "\n";

  print_news_deltas ($_, $prev_version, $curr_version)
    foreach @news_file;

  $release_type eq 'stable'
    or print_changelog_deltas ($package_name, $prev_version);

  exit 0;
}

### Setup "GNU" style for perl-mode and cperl-mode.
## Local Variables:
## mode: perl
## perl-indent-level: 2
## perl-continued-statement-offset: 2
## perl-continued-brace-offset: 0
## perl-brace-offset: 0
## perl-brace-imaginary-offset: 0
## perl-label-offset: -2
## perl-extra-newline-before-brace: t
## perl-merge-trailing-else: nil
## eval: (add-hook 'write-file-hooks 'time-stamp)
## time-stamp-start: "my $VERSION = '"
## time-stamp-format: "%:y-%02m-%02d %02H:%02M"
## time-stamp-time-zone: "UTC"
## time-stamp-end: "'; # UTC"
## End:

path: build-aux/announce-gen


code:
/* A C macro for declaring that specific arguments must not be NULL.
   Copyright (C) 2009, 2010 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 3 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools
   that the values passed as arguments n, ..., m must be non-NULL pointers.
   n = 1 stands for the first argument, n = 2 for the second argument etc.  */
#ifndef _GL_ARG_NONNULL
# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3
#  define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params))
# else
#  define _GL_ARG_NONNULL(params)
# endif
#endif


code:
/* C++ compatible function declaration macros.
   Copyright (C) 2010 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 3 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef _GL_CXXDEFS_H
#define _GL_CXXDEFS_H

/* The three most frequent use cases of these macros are:

   * For providing a substitute for a function that is missing on some
     platforms, but is declared and works fine on the platforms on which
     it exists:

       #if @GNULIB_FOO@
       # if !@HAVE_FOO@
       _GL_FUNCDECL_SYS (foo, ...);
       # endif
       _GL_CXXALIAS_SYS (foo, ...);
       _GL_CXXALIASWARN (foo);
       #elif defined GNULIB_POSIXCHECK
       ...
       #endif

   * For providing a replacement for a function that exists on all platforms,
     but is broken/insufficient and needs to be replaced on some platforms:

       #if @GNULIB_FOO@
       # if @REPLACE_FOO@
       #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
       #   undef foo
       #   define foo rpl_foo
       #  endif
       _GL_FUNCDECL_RPL (foo, ...);
       _GL_CXXALIAS_RPL (foo, ...);
       # else
       _GL_CXXALIAS_SYS (foo, ...);
       # endif
       _GL_CXXALIASWARN (foo);
       #elif defined GNULIB_POSIXCHECK
       ...
       #endif

   * For providing a replacement for a function that exists on some platforms
     but is broken/insufficient and needs to be replaced on some of them and
     is additionally either missing or undeclared on some other platforms:

       #if @GNULIB_FOO@
       # if @REPLACE_FOO@
       #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
       #   undef foo
       #   define foo rpl_foo
       #  endif
       _GL_FUNCDECL_RPL (foo, ...);
       _GL_CXXALIAS_RPL (foo, ...);
       # else
       #  if !@HAVE_FOO@   or   if !@HAVE_DECL_FOO@
       _GL_FUNCDECL_SYS (foo, ...);
       #  endif
       _GL_CXXALIAS_SYS (foo, ...);
       # endif
       _GL_CXXALIASWARN (foo);
       #elif defined GNULIB_POSIXCHECK
       ...
       #endif
*/

/* _GL_EXTERN_C declaration;
   performs the declaration with C linkage.  */
#if defined __cplusplus
# define _GL_EXTERN_C extern "C"
#else
# define _GL_EXTERN_C extern
#endif

/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes);
   declares a replacement function, named rpl_func, with the given prototype,
   consisting of return type, parameters, and attributes.
   Example:
     _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...)
                                  _GL_ARG_NONNULL ((1)));
 */
#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \
  _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes)
#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \
  _GL_EXTERN_C rettype rpl_func parameters_and_attributes

/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes);
   declares the system function, named func, with the given prototype,
   consisting of return type, parameters, and attributes.
   Example:
     _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...)
                                  _GL_ARG_NONNULL ((1)));
 */
#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \
  _GL_EXTERN_C rettype func parameters_and_attributes

/* _GL_CXXALIAS_RPL (func, rettype, parameters);
   declares a C++ alias called GNULIB_NAMESPACE::func
   that redirects to rpl_func, if GNULIB_NAMESPACE is defined.
   Example:
     _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...));
 */
#define _GL_CXXALIAS_RPL(func,rettype,parameters) \
  _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters)
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
    namespace GNULIB_NAMESPACE                                \
    {                                                         \
      rettype (*const func) parameters = ::rpl_func;          \
    }                                                         \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters);
   is like  _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters);
   except that the C function rpl_func may have a slightly different
   declaration.  A cast is used to silence the "invalid conversion" error
   that would otherwise occur.  */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
    namespace GNULIB_NAMESPACE                                     \
    {                                                              \
      rettype (*const func) parameters =                           \
        reinterpret_cast<rettype(*)parameters>(::rpl_func);        \
    }                                                              \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

/* _GL_CXXALIAS_SYS (func, rettype, parameters);
   declares a C++ alias called GNULIB_NAMESPACE::func
   that redirects to the system provided function func, if GNULIB_NAMESPACE
   is defined.
   Example:
     _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...));
 */
#if defined __cplusplus && defined GNULIB_NAMESPACE
  /* If we were to write
       rettype (*const func) parameters = ::func;
     like above in _GL_CXXALIAS_RPL_1, the compiler could optimize calls
     better (remove an indirection through a 'static' pointer variable),
     but then the _GL_CXXALIASWARN macro below would cause a warning not only
     for uses of ::func but also for uses of GNULIB_NAMESPACE::func.  */
# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
    namespace GNULIB_NAMESPACE                     \
    {                                              \
      static rettype (*func) parameters = ::func;  \
    }                                              \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_SYS(func,rettype,parameters) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters);
   is like  _GL_CXXALIAS_SYS (func, rettype, parameters);
   except that the C function func may have a slightly different declaration.
   A cast is used to silence the "invalid conversion" error that would
   otherwise occur.  */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
    namespace GNULIB_NAMESPACE                          \
    {                                                   \
      static rettype (*func) parameters =               \
        reinterpret_cast<rettype(*)parameters>(::func); \
    }                                                   \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2);
   is like  _GL_CXXALIAS_SYS (func, rettype, parameters);
   except that the C function is picked among a set of overloaded functions,
   namely the one with rettype2 and parameters2.  Two consecutive casts
   are used to silence the "cannot find a match" and "invalid conversion"
   errors that would otherwise occur.  */
#if defined __cplusplus && defined GNULIB_NAMESPACE
  /* The outer cast must be a reinterpret_cast.
     The inner cast: When the function is defined as a set of overloaded
     functions, it works as a static_cast<>, choosing the designated variant.
     When the function is defined as a single variant, it works as a
     reinterpret_cast<>. The parenthesized cast syntax works both ways.  */
# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
    namespace GNULIB_NAMESPACE                                                \
    {                                                                         \
      static rettype (*func) parameters =                                     \
        reinterpret_cast<rettype(*)parameters>(                               \
          (rettype2(*)parameters2)(::func));                                  \
    }                                                                         \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#else
# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

/* _GL_CXXALIASWARN (func);
   causes a warning to be emitted when ::func is used but not when
   GNULIB_NAMESPACE::func is used.  func must be defined without overloaded
   variants.  */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIASWARN(func) \
   _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE)
# define _GL_CXXALIASWARN_1(func,namespace) \
   _GL_CXXALIASWARN_2 (func, namespace)
/* To work around GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
   we enable the warning only when not optimizing.  */
# if !__OPTIMIZE__
#  define _GL_CXXALIASWARN_2(func,namespace) \
    _GL_WARN_ON_USE (func, \
                     "The symbol ::" #func " refers to the system function. " \
                     "Use " #namespace "::" #func " instead.")
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
#  define _GL_CXXALIASWARN_2(func,namespace) \
     extern __typeof__ (func) func
# else
#  define _GL_CXXALIASWARN_2(func,namespace) \
     _GL_EXTERN_C int _gl_cxxalias_dummy
# endif
#else
# define _GL_CXXALIASWARN(func) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes);
   causes a warning to be emitted when the given overloaded variant of ::func
   is used but not when GNULIB_NAMESPACE::func is used.  */
#if defined __cplusplus && defined GNULIB_NAMESPACE
# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
   _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \
                        GNULIB_NAMESPACE)
# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \
   _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace)
/* To work around GCC bug <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43881>,
   we enable the warning only when not optimizing.  */
# if !__OPTIMIZE__
#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
    _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \
                         "The symbol ::" #func " refers to the system function. " \
                         "Use " #namespace "::" #func " instead.")
# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING
#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
     extern __typeof__ (func) func
# else
#  define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \
     _GL_EXTERN_C int _gl_cxxalias_dummy
# endif
#else
# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \
    _GL_EXTERN_C int _gl_cxxalias_dummy
#endif

#endif /* _GL_CXXDEFS_H */


code:
#! /bin/sh
# Output a system dependent set of variables, describing how to set the
# run time search path of shared libraries in an executable.
#
#   Copyright 1996-2010 Free Software Foundation, Inc.
#   Taken from GNU libtool, 2001
#   Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
#
#   This file is free software; the Free Software Foundation gives
#   unlimited permission to copy and/or distribute it, with or without
#   modifications, as long as this notice is preserved.
#
# The first argument passed to this file is the canonical host specification,
#    CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or
#    CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
# should be set by the caller.
#
# The set of defined variables is at the end of this script.

# Known limitations:
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
#   than 256 bytes, otherwise the compiler driver will dump core. The only
#   known workaround is to choose shorter directory names for the build
#   directory and/or the installation directory.

# All known linkers require a `.a' archive for static linking (except MSVC,
# which needs '.lib').
libext=a
shrext=.so

host="$1"
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`

# Code taken from libtool.m4's _LT_CC_BASENAME.

for cc_temp in $CC""; do
  case $cc_temp in
    compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
    distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
    \-*) ;;
    *) break;;
  esac
done
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`

# Code taken from libtool.m4's _LT_COMPILER_PIC.

wl=
if test "$GCC" = yes; then
  wl='-Wl,'
else
  case "$host_os" in
    aix*)
      wl='-Wl,'
      ;;
    darwin*)
      case $cc_basename in
        xlc*)
          wl='-Wl,'
          ;;
      esac
      ;;
    mingw* | cygwin* | pw32* | os2* | cegcc*)
      ;;
    hpux9* | hpux10* | hpux11*)
      wl='-Wl,'
      ;;
    irix5* | irix6* | nonstopux*)
      wl='-Wl,'
      ;;
    newsos6)
      ;;
    linux* | k*bsd*-gnu)
      case $cc_basename in
        ecc*)
          wl='-Wl,'
          ;;
        icc* | ifort*)
          wl='-Wl,'
          ;;
        lf95*)
          wl='-Wl,'
          ;;
        pgcc | pgf77 | pgf90)
          wl='-Wl,'
          ;;
        ccc*)
          wl='-Wl,'
          ;;
        como)
          wl='-lopt='
          ;;
        *)
          case `$CC -V 2>&1 | sed 5q` in
            *Sun\ C*)
              wl='-Wl,'
              ;;
          esac
          ;;
      esac
      ;;
    osf3* | osf4* | osf5*)
      wl='-Wl,'
      ;;
    rdos*)
      ;;
    solaris*)
      wl='-Wl,'
      ;;
    sunos4*)
      wl='-Qoption ld '
      ;;
    sysv4 | sysv4.2uw2* | sysv4.3*)
      wl='-Wl,'
      ;;
    sysv4*MP*)
      ;;
    sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
      wl='-Wl,'
      ;;
    unicos*)
      wl='-Wl,'
      ;;
    uts4*)
      ;;
  esac
fi

# Code taken from libtool.m4's _LT_LINKER_SHLIBS.

hardcode_libdir_flag_spec=
hardcode_libdir_separator=
hardcode_direct=no
hardcode_minus_L=no

case "$host_os" in
  cygwin* | mingw* | pw32* | cegcc*)
    # FIXME: the MSVC++ port hasn't been tested in a loooong time
    # When not using gcc, we currently assume that we are using
    # Microsoft Visual C++.
    if test "$GCC" != yes; then
      with_gnu_ld=no
    fi
    ;;
  interix*)
    # we just hope/assume this is gcc and not c89 (= MSVC++)
    with_gnu_ld=yes
    ;;
  openbsd*)
    with_gnu_ld=no
    ;;
esac

ld_shlibs=yes
if test "$with_gnu_ld" = yes; then
  # Set some defaults for GNU ld with shared library support. These
  # are reset later if shared libraries are not supported. Putting them
  # here allows them to be overridden if necessary.
  # Unlike libtool, we use -rpath here, not --rpath, since the documented
  # option of GNU ld is called -rpath, not --rpath.
  hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
  case "$host_os" in
    aix[3-9]*)
      # On AIX/PPC, the GNU linker is very broken
      if test "$host_cpu" != ia64; then
        ld_shlibs=no
      fi
      ;;
    amigaos*)
      hardcode_libdir_flag_spec='-L$libdir'
      hardcode_minus_L=yes
      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
      # that the semantics of dynamic libraries on AmigaOS, at least up
      # to version 4, is to share data among multiple programs linked
      # with the same dynamic library.  Since this doesn't match the
      # behavior of shared libraries on other platforms, we cannot use
      # them.
      ld_shlibs=no
      ;;
    beos*)
      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
        :
      else
        ld_shlibs=no
      fi
      ;;
    cygwin* | mingw* | pw32* | cegcc*)
      # hardcode_libdir_flag_spec is actually meaningless, as there is
      # no search path for DLLs.
      hardcode_libdir_flag_spec='-L$libdir'
      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
        :
      else
        ld_shlibs=no
      fi
      ;;
    interix[3-9]*)
      hardcode_direct=no
      hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
      ;;
    gnu* | linux* | k*bsd*-gnu)
      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
        :
      else
        ld_shlibs=no
      fi
      ;;
    netbsd*)
      ;;
    solaris*)
      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
        ld_shlibs=no
      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
        :
      else
        ld_shlibs=no
      fi
      ;;
    sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
      case `$LD -v 2>&1` in
        *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
          ld_shlibs=no
          ;;
        *)
          if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
            hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
          else
            ld_shlibs=no
          fi
          ;;
      esac
      ;;
    sunos4*)
      hardcode_direct=yes
      ;;
    *)
      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
        :
      else
        ld_shlibs=no
      fi
      ;;
  esac
  if test "$ld_shlibs" = no; then
    hardcode_libdir_flag_spec=
  fi
else
  case "$host_os" in
    aix3*)
      # Note: this linker hardcodes the directories in LIBPATH if there
      # are no directories specified by -L.
      hardcode_minus_L=yes
      if test "$GCC" = yes; then
        # Neither direct hardcoding nor static linking is supported with a
        # broken collect2.
        hardcode_direct=unsupported
      fi
      ;;
    aix[4-9]*)
      if test "$host_cpu" = ia64; then
        # On IA64, the linker does run time linking by default, so we don't
        # have to do anything special.
        aix_use_runtimelinking=no
      else
        aix_use_runtimelinking=no
        # Test if we are trying to use run time linking or normal
        # AIX style linking. If -brtl is somewhere in LDFLAGS, we
        # need to do runtime linking.
        case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
          for ld_flag in $LDFLAGS; do
            if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
              aix_use_runtimelinking=yes
              break
            fi
          done
          ;;
        esac
      fi
      hardcode_direct=yes
      hardcode_libdir_separator=':'
      if test "$GCC" = yes; then
        case $host_os in aix4.[012]|aix4.[012].*)
          collect2name=`${CC} -print-prog-name=collect2`
          if test -f "$collect2name" && \
            strings "$collect2name" | grep resolve_lib_name >/dev/null
          then
            # We have reworked collect2
            :
          else
            # We have old collect2
            hardcode_direct=unsupported
            hardcode_minus_L=yes
            hardcode_libdir_flag_spec='-L$libdir'
            hardcode_libdir_separator=
          fi
          ;;
        esac
      fi
      # Begin _LT_AC_SYS_LIBPATH_AIX.
      echo 'int main () { return 0; }' > conftest.c
      ${CC} ${LDFLAGS} conftest.c -o conftest
      aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
}'`
      if test -z "$aix_libpath"; then
        aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
}'`
      fi
      if test -z "$aix_libpath"; then
        aix_libpath="/usr/lib:/lib"
      fi
      rm -f conftest.c conftest
      # End _LT_AC_SYS_LIBPATH_AIX.
      if test "$aix_use_runtimelinking" = yes; then
        hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
      else
        if test "$host_cpu" = ia64; then
          hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
        else
          hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
        fi
      fi
      ;;
    amigaos*)
      hardcode_libdir_flag_spec='-L$libdir'
      hardcode_minus_L=yes
      # see comment about different semantics on the GNU ld section
      ld_shlibs=no
      ;;
    bsdi[45]*)
      ;;
    cygwin* | mingw* | pw32* | cegcc*)
      # When not using gcc, we currently assume that we are using
      # Microsoft Visual C++.
      # hardcode_libdir_flag_spec is actually meaningless, as there is
      # no search path for DLLs.
      hardcode_libdir_flag_spec=' '
      libext=lib
      ;;
    darwin* | rhapsody*)
      hardcode_direct=no
      if test "$GCC" = yes ; then
        :
      else
        case $cc_basename in
          xlc*)
            ;;
          *)
            ld_shlibs=no
            ;;
        esac
      fi
      ;;
    dgux*)
      hardcode_libdir_flag_spec='-L$libdir'
      ;;
    freebsd1*)
      ld_shlibs=no
      ;;
    freebsd2.2*)
      hardcode_libdir_flag_spec='-R$libdir'
      hardcode_direct=yes
      ;;
    freebsd2*)
      hardcode_direct=yes
      hardcode_minus_L=yes
      ;;
    freebsd* | dragonfly*)
      hardcode_libdir_flag_spec='-R$libdir'
      hardcode_direct=yes
      ;;
    hpux9*)
      hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
      hardcode_libdir_separator=:
      hardcode_direct=yes
      # hardcode_minus_L: Not really in the search PATH,
      # but as the default location of the library.
      hardcode_minus_L=yes
      ;;
    hpux10*)
      if test "$with_gnu_ld" = no; then
        hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
        hardcode_libdir_separator=:
        hardcode_direct=yes
        # hardcode_minus_L: Not really in the search PATH,
        # but as the default location of the library.
        hardcode_minus_L=yes
      fi
      ;;
    hpux11*)
      if test "$with_gnu_ld" = no; then
        hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
        hardcode_libdir_separator=:
        case $host_cpu in
          hppa*64*|ia64*)
            hardcode_direct=no
            ;;
          *)
            hardcode_direct=yes
            # hardcode_minus_L: Not really in the search PATH,
            # but as the default location of the library.
            hardcode_minus_L=yes
            ;;
        esac
      fi
      ;;
    irix5* | irix6* | nonstopux*)
      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
      hardcode_libdir_separator=:
      ;;
    netbsd*)
      hardcode_libdir_flag_spec='-R$libdir'
      hardcode_direct=yes
      ;;
    newsos6)
      hardcode_direct=yes
      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
      hardcode_libdir_separator=:
      ;;
    openbsd*)
      if test -f /usr/libexec/ld.so; then
        hardcode_direct=yes
        if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
          hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
        else
          case "$host_os" in
            openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
              hardcode_libdir_flag_spec='-R$libdir'
              ;;
            *)
              hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
              ;;
          esac
        fi
      else
        ld_shlibs=no
      fi
      ;;
    os2*)
      hardcode_libdir_flag_spec='-L$libdir'
      hardcode_minus_L=yes
      ;;
    osf3*)
      hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
      hardcode_libdir_separator=:
      ;;
    osf4* | osf5*)
      if test "$GCC" = yes; then
        hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
      else
        # Both cc and cxx compiler support -rpath directly
        hardcode_libdir_flag_spec='-rpath $libdir'
      fi
      hardcode_libdir_separator=:
      ;;
    solaris*)
      hardcode_libdir_flag_spec='-R$libdir'
      ;;
    sunos4*)
      hardcode_libdir_flag_spec='-L$libdir'
      hardcode_direct=yes
      hardcode_minus_L=yes
      ;;
    sysv4)
      case $host_vendor in
        sni)
          hardcode_direct=yes # is this really true???
          ;;
        siemens)
          hardcode_direct=no
          ;;
        motorola)
          hardcode_direct=no #Motorola manual says yes, but my tests say they lie
          ;;
      esac
      ;;
    sysv4.3*)
      ;;
    sysv4*MP*)
      if test -d /usr/nec; then
        ld_shlibs=yes
      fi
      ;;
    sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
      ;;
    sysv5* | sco3.2v5* | sco5v6*)
      hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
      hardcode_libdir_separator=':'
      ;;
    uts4*)
      hardcode_libdir_flag_spec='-L$libdir'
      ;;
    *)
      ld_shlibs=no
      ;;
  esac
fi

# Check dynamic linker characteristics
# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
# only about the one the linker finds when passed -lNAME. This is the last
# element of library_names_spec in libtool.m4, or possibly two of them if the
# linker has special search rules.
library_names_spec=      # the last element of library_names_spec in libtool.m4
libname_spec='lib$name'
case "$host_os" in
  aix3*)
    library_names_spec='$libname.a'
    ;;
  aix[4-9]*)
    library_names_spec='$libname$shrext'
    ;;
  amigaos*)
    library_names_spec='$libname.a'
    ;;
  beos*)
    library_names_spec='$libname$shrext'
    ;;
  bsdi[45]*)
    library_names_spec='$libname$shrext'
    ;;
  cygwin* | mingw* | pw32* | cegcc*)
    shrext=.dll
    library_names_spec='$libname.dll.a $libname.lib'
    ;;
  darwin* | rhapsody*)
    shrext=.dylib
    library_names_spec='$libname$shrext'
    ;;
  dgux*)
    library_names_spec='$libname$shrext'
    ;;
  freebsd1*)
    ;;
  freebsd* | dragonfly*)
    case "$host_os" in
      freebsd[123]*)
        library_names_spec='$libname$shrext$versuffix' ;;
      *)
        library_names_spec='$libname$shrext' ;;
    esac
    ;;
  gnu*)
    library_names_spec='$libname$shrext'
    ;;
  hpux9* | hpux10* | hpux11*)
    case $host_cpu in
      ia64*)
        shrext=.so
        ;;
      hppa*64*)
        shrext=.sl
        ;;
      *)
        shrext=.sl
        ;;
    esac
    library_names_spec='$libname$shrext'
    ;;
  interix[3-9]*)
    library_names_spec='$libname$shrext'
    ;;
  irix5* | irix6* | nonstopux*)
    library_names_spec='$libname$shrext'
    case "$host_os" in
      irix5* | nonstopux*)
        libsuff= shlibsuff=
        ;;
      *)
        case $LD in
          *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
          *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
          *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
          *) libsuff= shlibsuff= ;;
        esac
        ;;
    esac
    ;;
  linux*oldld* | linux*aout* | linux*coff*)
    ;;
  linux* | k*bsd*-gnu)
    library_names_spec='$libname$shrext'
    ;;
  knetbsd*-gnu)
    library_names_spec='$libname$shrext'
    ;;
  netbsd*)
    library_names_spec='$libname$shrext'
    ;;
  newsos6)
    library_names_spec='$libname$shrext'
    ;;
  nto-qnx*)
    library_names_spec='$libname$shrext'
    ;;
  openbsd*)
    library_names_spec='$libname$shrext$versuffix'
    ;;
  os2*)
    libname_spec='$name'
    shrext=.dll
    library_names_spec='$libname.a'
    ;;
  osf3* | osf4* | osf5*)
    library_names_spec='$libname$shrext'
    ;;
  rdos*)
    ;;
  solaris*)
    library_names_spec='$libname$shrext'
    ;;
  sunos4*)
    library_names_spec='$libname$shrext$versuffix'
    ;;
  sysv4 | sysv4.3*)
    library_names_spec='$libname$shrext'
    ;;
  sysv4*MP*)
    library_names_spec='$libname$shrext'
    ;;
  sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
    library_names_spec='$libname$shrext'
    ;;
  uts4*)
    library_names_spec='$libname$shrext'
    ;;
esac

sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`

LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF

# How to pass a linker flag through the compiler.
wl="$escaped_wl"

# Static library suffix (normally "a").
libext="$libext"

# Shared library suffix (normally "so").
shlibext="$shlibext"

# Format of library name prefix.
libname_spec="$escaped_libname_spec"

# Library names that the linker finds when passed -lNAME.
library_names_spec="$escaped_library_names_spec"

# Flag to hardcode \$libdir into a binary during linking.
# This must work even if \$libdir does not exist.
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"

# Whether we need a single -rpath flag with a separated argument.
hardcode_libdir_separator="$hardcode_libdir_separator"

# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
# resulting binary.
hardcode_direct="$hardcode_direct"

# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
# resulting binary.
hardcode_minus_L="$hardcode_minus_L"

EOF


code:
#!/bin/sh -e
# gendocs.sh -- generate a GNU manual in many formats.  This script is
#   mentioned in maintain.texi.  See the help message below for usage details.

scriptversion=2010-05-04.09

# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
# 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 3 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, see <http://www.gnu.org/licenses/>.
#
# Original author: Mohit Agarwal.
# Send bug reports and any other correspondence to bug-texinfo@gnu.org.

prog=`basename "$0"`
srcdir=`pwd`

scripturl="http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~/texinfo/texinfo/util/gendocs.sh"
templateurl="http://savannah.gnu.org/cgi-bin/viewcvs/~checkout~/texinfo/texinfo/util/gendocs_template"

: ${SETLANG="env LANG= LC_MESSAGES= LC_ALL= LANGUAGE="}
: ${MAKEINFO="makeinfo"}
: ${TEXI2DVI="texi2dvi -t @finalout"}
: ${DVIPS="dvips"}
: ${DOCBOOK2HTML="docbook2html"}
: ${DOCBOOK2PDF="docbook2pdf"}
: ${DOCBOOK2PS="docbook2ps"}
: ${DOCBOOK2TXT="docbook2txt"}
: ${GENDOCS_TEMPLATE_DIR="."}
: ${TEXI2HTML="texi2html"}
unset CDPATH
unset use_texi2html

version="gendocs.sh $scriptversion

Copyright 2009 Free Software Foundation, Inc.
There is NO warranty.  You may redistribute this software
under the terms of the GNU General Public License.
For more information about these matters, see the files named COPYING."

usage="Usage: $prog [OPTION]... PACKAGE MANUAL-TITLE

Generate various output formats from PACKAGE.texinfo (or .texi or .txi) source.
See the GNU Maintainers document for a more extensive discussion:
  http://www.gnu.org/prep/maintain_toc.html

Options:
  -s SRCFILE  read Texinfo from SRCFILE, instead of PACKAGE.{texinfo|texi|txi}
  -o OUTDIR   write files into OUTDIR, instead of manual/.
  --email ADR use ADR as contact in generated web pages.
  --docbook   convert to DocBook too (xml, txt, html, pdf and ps).
  --html ARG  pass indicated ARG to makeinfo or texi2html for HTML targets.
  --texi2html use texi2html to generate HTML targets.
  --help      display this help and exit successfully.
  --version   display version information and exit successfully.

Simple example: $prog --email bug-gnu-emacs@gnu.org emacs \"GNU Emacs Manual\"

Typical sequence:
  cd PACKAGESOURCE/doc
  wget \"$scripturl\"
  wget \"$templateurl\"
  $prog --email BUGLIST MANUAL \"GNU MANUAL - One-line description\"

Output will be in a new subdirectory \"manual\" (by default, use -o OUTDIR
to override).  Move all the new files into your web CVS tree, as
explained in the Web Pages node of maintain.texi.

Please use the --email ADDRESS option to specify your bug-reporting
address in the generated HTML pages.

MANUAL-TITLE is included as part of the HTML <title> of the overall
manual/index.html file.  It should include the name of the package being
documented.  manual/index.html is created by substitution from the file
$GENDOCS_TEMPLATE_DIR/gendocs_template.  (Feel free to modify the
generic template for your own purposes.)

If you have several manuals, you'll need to run this script several
times with different MANUAL values, specifying a different output
directory with -o each time.  Then write (by hand) an overall index.html
with links to them all.

If a manual's Texinfo sources are spread across several directories,
first copy or symlink all Texinfo sources into a single directory.
(Part of the script's work is to make a tar.gz of the sources.)

You can set the environment variables MAKEINFO, TEXI2DVI, and DVIPS to
control the programs that get executed, and GENDOCS_TEMPLATE_DIR to
control where the gendocs_template file is looked for.  (With --docbook,
the environment variables DOCBOOK2HTML, DOCBOOK2PDF, DOCBOOK2PS, and
DOCBOOK2TXT are also respected.)

By default, makeinfo is run in the default (English) locale, since
that's the language of most Texinfo manuals.  If you happen to have a
non-English manual and non-English web site, see the SETLANG setting
in the source.

Email bug reports or enhancement requests to bug-texinfo@gnu.org.
"

calcsize()
{
  size=`ls -ksl $1 | awk '{print $1}'`
  echo $size
}

MANUAL_TITLE=
PACKAGE=
EMAIL=webmasters@gnu.org  # please override with --email
htmlarg=
outdir=manual
srcfile=

while test $# -gt 0; do
  case $1 in
    --email) shift; EMAIL=$1;;
    --help) echo "$usage"; exit 0;;
    --version) echo "$version"; exit 0;;
    -s) shift; srcfile=$1;;
    -o) shift; outdir=$1;;
    --docbook) docbook=yes;;
    --html) shift; htmlarg=$1;;
    --texi2html) use_texi2html=1;;
    -*)
      echo "$0: Unknown option \`$1'." >&2
      echo "$0: Try \`--help' for more information." >&2
      exit 1;;
    *)
      if test -z "$PACKAGE"; then
        PACKAGE=$1
      elif test -z "$MANUAL_TITLE"; then
        MANUAL_TITLE=$1
      else
        echo "$0: extra non-option argument \`$1'." >&2
        exit 1
      fi;;
  esac
  shift
done

# For most of the following, the base name is just $PACKAGE
base=$PACKAGE

if test -n "$srcfile"; then
  # but here, we use the basename of $srcfile
  base=`basename "$srcfile"`
  case $base in
    *.txi|*.texi|*.texinfo) base=`echo "$base"|sed 's/\.[texinfo]*$//'`;;
  esac
  PACKAGE=$base
elif test -s "$srcdir/$PACKAGE.texinfo"; then
  srcfile=$srcdir/$PACKAGE.texinfo
elif test -s "$srcdir/$PACKAGE.texi"; then
  srcfile=$srcdir/$PACKAGE.texi
elif test -s "$srcdir/$PACKAGE.txi"; then
  srcfile=$srcdir/$PACKAGE.txi
else
  echo "$0: cannot find .texinfo or .texi or .txi for $PACKAGE in $srcdir." >&2
  exit 1
fi

if test ! -r $GENDOCS_TEMPLATE_DIR/gendocs_template; then
  echo "$0: cannot read $GENDOCS_TEMPLATE_DIR/gendocs_template." >&2
  echo "$0: it is available from $templateurl." >&2
  exit 1
fi

case $outdir in
  /*) dotdot_outdir="$outdir";;
  *) dotdot_outdir="../$outdir";;
esac

echo Generating output formats for $srcfile

cmd="$SETLANG $MAKEINFO -o $PACKAGE.info \"$srcfile\""
echo "Generating info files... ($cmd)"
eval "$cmd"
mkdir -p $outdir/
tar czf $outdir/$PACKAGE.info.tar.gz $PACKAGE.info*
info_tgz_size=`calcsize $outdir/$PACKAGE.info.tar.gz`
# do not mv the info files, there's no point in having them available
# separately on the web.

cmd="${TEXI2DVI} \"$srcfile\""
echo "Generating dvi ... ($cmd)"
eval "$cmd"

# now, before we compress dvi:
echo Generating postscript...
${DVIPS} $PACKAGE -o
gzip -f -9 $PACKAGE.ps
ps_gz_size=`calcsize $PACKAGE.ps.gz`
mv $PACKAGE.ps.gz $outdir/

# compress/finish dvi:
gzip -f -9 $PACKAGE.dvi
dvi_gz_size=`calcsize $PACKAGE.dvi.gz`
mv $PACKAGE.dvi.gz $outdir/

cmd="${TEXI2DVI} --pdf \"$srcfile\""
echo "Generating pdf ... ($cmd)"
eval "$cmd"
pdf_size=`calcsize $PACKAGE.pdf`
mv $PACKAGE.pdf $outdir/

cmd="$SETLANG $MAKEINFO -o $PACKAGE.txt --no-split --no-headers \"$srcfile\""
echo "Generating ASCII... ($cmd)"
eval "$cmd"
ascii_size=`calcsize $PACKAGE.txt`
gzip -f -9 -c $PACKAGE.txt >$outdir/$PACKAGE.txt.gz
ascii_gz_size=`calcsize $outdir/$PACKAGE.txt.gz`
mv $PACKAGE.txt $outdir/

html_split()
{
  opt="--split=$1 $htmlarg --node-files"
  cmd="$SETLANG $TEXI2HTML --output $PACKAGE.html $opt \"$srcfile\""
  echo "Generating html by $1... ($cmd)"
  eval "$cmd"
  split_html_dir=$PACKAGE.html
  (
    cd ${split_html_dir} || exit 1
    ln -sf ${PACKAGE}.html index.html
    tar -czf $dotdot_outdir/${PACKAGE}.html_$1.tar.gz -- *.html
  )
  eval html_$1_tgz_size=`calcsize $outdir/${PACKAGE}.html_$1.tar.gz`
  rm -f $outdir/html_$1/*.html
  mkdir -p $outdir/html_$1/
  mv ${split_html_dir}/*.html $outdir/html_$1/
  rmdir ${split_html_dir}
}

if test -z "$use_texi2html"; then
  opt="--no-split --html -o $PACKAGE.html $htmlarg"
  cmd="$SETLANG $MAKEINFO $opt \"$srcfile\""
  echo "Generating monolithic html... ($cmd)"
  rm -rf $PACKAGE.html  # in case a directory is left over
  eval "$cmd"
  html_mono_size=`calcsize $PACKAGE.html`
  gzip -f -9 -c $PACKAGE.html >$outdir/$PACKAGE.html.gz
  html_mono_gz_size=`calcsize $outdir/$PACKAGE.html.gz`
  mv $PACKAGE.html $outdir/

  cmd="$SETLANG $MAKEINFO --html -o $PACKAGE.html $htmlarg \"$srcfile\""
  echo "Generating html by node... ($cmd)"
  eval "$cmd"
  split_html_dir=$PACKAGE.html
  (
   cd ${split_html_dir} || exit 1
   tar -czf $dotdot_outdir/${PACKAGE}.html_node.tar.gz -- *.html
  )
  html_node_tgz_size=`calcsize $outdir/${PACKAGE}.html_node.tar.gz`
  rm -f $outdir/html_node/*.html
  mkdir -p $outdir/html_node/
  mv ${split_html_dir}/*.html $outdir/html_node/
  rmdir ${split_html_dir}
else
  cmd="$SETLANG $TEXI2HTML --output $PACKAGE.html $htmlarg \"$srcfile\""
  echo "Generating monolithic html... ($cmd)"
  rm -rf $PACKAGE.html  # in case a directory is left over
  eval "$cmd"
  html_mono_size=`calcsize $PACKAGE.html`
  gzip -f -9 -c $PACKAGE.html >$outdir/$PACKAGE.html.gz
  html_mono_gz_size=`calcsize $outdir/$PACKAGE.html.gz`
  mv $PACKAGE.html $outdir/

  html_split node
  html_split chapter
  html_split section
fi

echo Making .tar.gz for sources...
d=`dirname $srcfile`
srcfiles=`ls $d/*.texinfo $d/*.texi $d/*.txi $d/*.eps 2>/dev/null` || true
tar cvzfh $outdir/$PACKAGE.texi.tar.gz $srcfiles
texi_tgz_size=`calcsize $outdir/$PACKAGE.texi.tar.gz`

if test -n "$docbook"; then
  cmd="$SETLANG $MAKEINFO -o - --docbook \"$srcfile\" > ${srcdir}/$PACKAGE-db.xml"
  echo "Generating docbook XML... ($cmd)"
  eval "$cmd"
  docbook_xml_size=`calcsize $PACKAGE-db.xml`
  gzip -f -9 -c $PACKAGE-db.xml >$outdir/$PACKAGE-db.xml.gz
  docbook_xml_gz_size=`calcsize $outdir/$PACKAGE-db.xml.gz`
  mv $PACKAGE-db.xml $outdir/

  cmd="${DOCBOOK2HTML} -o $split_html_db_dir ${outdir}/$PACKAGE-db.xml"
  echo "Generating docbook HTML... ($cmd)"
  eval "$cmd"
  split_html_db_dir=html_node_db
  (
    cd ${split_html_db_dir} || exit 1
    tar -czf $dotdot_outdir/${PACKAGE}.html_node_db.tar.gz -- *.html
  )
  html_node_db_tgz_size=`calcsize $outdir/${PACKAGE}.html_node_db.tar.gz`
  rm -f $outdir/html_node_db/*.html
  mkdir -p $outdir/html_node_db
  mv ${split_html_db_dir}/*.html $outdir/html_node_db/
  rmdir ${split_html_db_dir}

  cmd="${DOCBOOK2TXT} ${outdir}/$PACKAGE-db.xml"
  echo "Generating docbook ASCII... ($cmd)"
  eval "$cmd"
  docbook_ascii_size=`calcsize $PACKAGE-db.txt`
  mv $PACKAGE-db.txt $outdir/

  cmd="${DOCBOOK2PS} ${outdir}/$PACKAGE-db.xml"
  echo "Generating docbook PS... ($cmd)"
  eval "$cmd"
  gzip -f -9 -c $PACKAGE-db.ps >$outdir/$PACKAGE-db.ps.gz
  docbook_ps_gz_size=`calcsize $outdir/$PACKAGE-db.ps.gz`
  mv $PACKAGE-db.ps $outdir/

  cmd="${DOCBOOK2PDF} ${outdir}/$PACKAGE-db.xml"
  echo "Generating docbook PDF... ($cmd)"
  eval "$cmd"
  docbook_pdf_size=`calcsize $PACKAGE-db.pdf`
  mv $PACKAGE-db.pdf $outdir/
fi

echo "Writing index file..."
if test -z "$use_texi2html"; then
   CONDS="/%%IF  *HTML_SECTION%%/,/%%ENDIF  *HTML_SECTION%%/d;\
          /%%IF  *HTML_CHAPTER%%/,/%%ENDIF  *HTML_CHAPTER%%/d"
else
   CONDS="/%%ENDIF.*%%/d;/%%IF  *HTML_SECTION%%/d;/%%IF  *HTML_CHAPTER%%/d"
fi
curdate=`$SETLANG date '+%B %d, %Y'`
sed \
   -e "s!%%TITLE%%!$MANUAL_TITLE!g" \
   -e "s!%%EMAIL%%!$EMAIL!g" \
   -e "s!%%PACKAGE%%!$PACKAGE!g" \
   -e "s!%%DATE%%!$curdate!g" \
   -e "s!%%HTML_MONO_SIZE%%!$html_mono_size!g" \
   -e "s!%%HTML_MONO_GZ_SIZE%%!$html_mono_gz_size!g" \
   -e "s!%%HTML_NODE_TGZ_SIZE%%!$html_node_tgz_size!g" \
   -e "s!%%HTML_SECTION_TGZ_SIZE%%!$html_section_tgz_size!g" \
   -e "s!%%HTML_CHAPTER_TGZ_SIZE%%!$html_chapter_tgz_size!g" \
   -e "s!%%INFO_TGZ_SIZE%%!$info_tgz_size!g" \
   -e "s!%%DVI_GZ_SIZE%%!$dvi_gz_size!g" \
   -e "s!%%PDF_SIZE%%!$pdf_size!g" \
   -e "s!%%PS_GZ_SIZE%%!$ps_gz_size!g" \
   -e "s!%%ASCII_SIZE%%!$ascii_size!g" \
   -e "s!%%ASCII_GZ_SIZE%%!$ascii_gz_size!g" \
   -e "s!%%TEXI_TGZ_SIZE%%!$texi_tgz_size!g" \
   -e "s!%%DOCBOOK_HTML_NODE_TGZ_SIZE%%!$html_node_db_tgz_size!g" \
   -e "s!%%DOCBOOK_ASCII_SIZE%%!$docbook_ascii_size!g" \
   -e "s!%%DOCBOOK_PS_GZ_SIZE%%!$docbook_ps_gz_size!g" \
   -e "s!%%DOCBOOK_PDF_SIZE%%!$docbook_pdf_size!g" \
   -e "s!%%DOCBOOK_XML_SIZE%%!$docbook_xml_size!g" \
   -e "s!%%DOCBOOK_XML_GZ_SIZE%%!$docbook_xml_gz_size!g" \
   -e "s,%%SCRIPTURL%%,$scripturl,g" \
   -e "s!%%SCRIPTNAME%%!$prog!g" \
   -e "$CONDS" \
$GENDOCS_TEMPLATE_DIR/gendocs_template >$outdir/index.html

echo "Done, see $outdir/ subdirectory for new files."

# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End: